[gdal-dev] Potential dangerous use of CPLSetErrorHandler()
Even Rouault
even.rouault at mines-paris.org
Thu Feb 17 19:02:30 EST 2011
Hi Roger,
not sure if you are the appropriate recipient for this email, but as your name
appeared on http://cran.r-project.org/web/packages/rgdal/index.html I try my
chance ;-).
(CC'ing gdal-dev too since other users of GDAL might be interested by the
issue related with CPLSetErrorHandler() in other contexts)
I had a discussion with Bob on the GDAL IRC that you can follow here :
http://logs.qgis.org/gdal/%23gdal.2011-02-16.log and
http://logs.qgis.org/gdal/%23gdal.2011-02-17.log
Here's my analysis (based on https://r-forge.r-
project.org/scm/viewvc.php/trunk/src/gdal-bindings.cpp?view=markup&root=rgdal
) of what leads to the crash he noticed (of course I can be wrong since my
knowledge of R is null, so this is mostly based on guess) :
1) QGIS loads a plugin that loads RGDAL
2) When RGDAL is initialized, it installs a global error handler
__errorHandler with CPLSetErrorHandler()
3) Some functions of QGIS unrelated to RGDAL causes a CPLError() to be emitted
by GDAL/OGR
4) The global RGDAL error handler is triggered, causes the error() method to
be called which apparently causes a longjmp() to the R interpreter
5) At that point QGIS crashes as the longjmp() is inappropriate because R
isn't ready for being run at that point
So my suggestion would be not to use a global error handler set when RGDAL is
initialized, but rather for each binding of the GDAL API, install a local
error handler with CPLPushErrorHandler(__errorHandler) and uninstall it before
returning to R with CPLPopErrorHandler()
For example :
SEXP
RGDAL_GetDescription(SEXP sxpObj) {
void *pGDALObj = getGDALObjPtr(sxpObj);
CPLPushErrorHandler(__errorHandler);
const char *desc = ((GDALMajorObject *)pGDALObj)->GetDescription();
CPLPopErrorHandler();
return(mkString_safe(desc));
}
This is going to be quite painfull since you have to do this for each GDAL
method you bind, and be careful to correctly pair CPLPushErrorHandler() /
CPLPopErrorHandler() (the later being the easiest to forget in unsuual code
paths, such as error code paths).
Best regards,
Even
More information about the gdal-dev
mailing list