Skip to content

Commit

Permalink
Fix for ticket #110.
Browse files Browse the repository at this point in the history
To protect the process from being terminated by GRASS (>= 6.3), we use setjmp/longjmp functions.


git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@7299 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
wonder committed Oct 24, 2007
1 parent fa1a8bc commit c74003e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
15 changes: 13 additions & 2 deletions src/plugins/grass/qgsgrassselect.cpp
Expand Up @@ -394,8 +394,19 @@ QStringList QgsGrassSelect::vectorLayers ( QString gisdbase,
QgsGrass::resetError();
Vect_set_open_level (2);
struct Map_info map;
int level = Vect_open_old_head (&map, (char *) mapName.ascii(),
(char *) mapset.ascii());
int level;

// Mechanism to recover from fatal errors in GRASS
// Since fatal error routine in GRASS >= 6.3 terminates the process,
// we use setjmp() to set recovery place in case of a fatal error.
// Call to setjmp() returns 0 first time. In case of fatal error,
// our error routine uses longjmp() to come back to this context,
// this time setjmp() will return non-zero value and we can continue...
if (setjmp(QgsGrass::fatalErrorEnv()) == 0)
{
level = Vect_open_old_head (&map, (char *) mapName.ascii(),
(char *) mapset.ascii());
}

if ( QgsGrass::getError() == QgsGrass::FATAL ) {
std::cerr << "Cannot open GRASS vector: " << QgsGrass::getErrorMessage().toLocal8Bit().data() << std::endl;
Expand Down
20 changes: 17 additions & 3 deletions src/providers/grass/qgsgrass.cpp
Expand Up @@ -347,18 +347,26 @@ QString QgsGrass::mMapsetLock;
QString QgsGrass::mGisrc;
QString QgsGrass::mTmp;

jmp_buf QgsGrass::mFatalErrorEnv;

int QgsGrass::error_routine ( char *msg, int fatal) {
return error_routine((const char*) msg, fatal);
}

int QgsGrass::error_routine ( const char *msg, int fatal) {
std::cerr << "error_routine (fatal = " << fatal << "): " << msg << std::endl;

if ( fatal ) error = FATAL;
else error = WARNING;

error_message = msg;

if ( fatal )
{
error = FATAL;
// we have to do a long jump here, otherwise GRASS >= 6.3 will kill our process
longjmp(mFatalErrorEnv, 1);
}
else
error = WARNING;

return 1;
}

Expand All @@ -374,6 +382,12 @@ QString QgsGrass::getErrorMessage ( void ) {
return error_message;
}

jmp_buf& QgsGrass::fatalErrorEnv()
{
return mFatalErrorEnv;
}


QString QgsGrass::openMapset ( QString gisdbase, QString location, QString mapset )
{
#ifdef QGISDEBUG
Expand Down
10 changes: 9 additions & 1 deletion src/providers/grass/qgsgrass.h
Expand Up @@ -22,6 +22,8 @@ extern "C" {
#include <grass/form.h>
}

#include <setjmp.h>

/*!
Methods for C library initialization and error handling.
*/
Expand Down Expand Up @@ -151,7 +153,10 @@ class QgsGrass {
static int versionMinor();
static int versionRelease();
static QString versionString();

static jmp_buf& fatalErrorEnv();


private:
static int initialized; // Set to 1 after initialization
static bool active; // is active mode
Expand All @@ -175,7 +180,10 @@ class QgsGrass {
// Current mapset GISRC file path
static QString mGisrc;
// Temporary directory where GISRC and sockets are stored
static QString mTmp;
static QString mTmp;

// Context saved before a call to routine that can produce a fatal error
static jmp_buf mFatalErrorEnv;
};

#endif // QGSGRASS_H

0 comments on commit c74003e

Please sign in to comment.