Skip to content
Permalink
Browse files

Fix for ticket #110.

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
wonder committed Oct 24, 2007
1 parent fa1a8bc commit c74003e8fe25c8a369bbf61d81689e977cb25b7c
Showing with 39 additions and 6 deletions.
  1. +13 −2 src/plugins/grass/qgsgrassselect.cpp
  2. +17 −3 src/providers/grass/qgsgrass.cpp
  3. +9 −1 src/providers/grass/qgsgrass.h
@@ -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;
@@ -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;
}

@@ -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
@@ -22,6 +22,8 @@ extern "C" {
#include <grass/form.h>
}

#include <setjmp.h>

/*!
Methods for C library initialization and error handling.
*/
@@ -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
@@ -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.
You can’t perform that action at this time.