diff --git a/src/plugins/grass/qgsgrassselect.cpp b/src/plugins/grass/qgsgrassselect.cpp index 02f8e4190d0..ed1aa954e22 100644 --- a/src/plugins/grass/qgsgrassselect.cpp +++ b/src/plugins/grass/qgsgrassselect.cpp @@ -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; diff --git a/src/providers/grass/qgsgrass.cpp b/src/providers/grass/qgsgrass.cpp index f9c0059e298..bcf5931d473 100644 --- a/src/providers/grass/qgsgrass.cpp +++ b/src/providers/grass/qgsgrass.cpp @@ -347,6 +347,8 @@ 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); } @@ -354,11 +356,17 @@ int QgsGrass::error_routine ( char *msg, int 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 diff --git a/src/providers/grass/qgsgrass.h b/src/providers/grass/qgsgrass.h index 9fc601460e7..a08549cfda5 100644 --- a/src/providers/grass/qgsgrass.h +++ b/src/providers/grass/qgsgrass.h @@ -22,6 +22,8 @@ extern "C" { #include } +#include + /*! Methods for C library initialization and error handling. */ @@ -151,7 +153,10 @@ public: 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 @@ private: // 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