-
Notifications
You must be signed in to change notification settings - Fork 0
Read-only mirror of "rgdal" from r-forge SVN.
r-forge/rgdal
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
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=rgda l ) 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). Actually, I'm just thinking that when an error actually triggers, the CPLPopErrorHandler() will not be called due to the longjmp() done in the error handler... So you probably needs to call CPLPopErrorHandler() in the error handler before it to call error() (a quick review of port/cpl_error.cpp leads me to think this is OK to do so, but this needs certainly some testing) Or other possibility, it might be dangerous that the error handler interrupts the GDAL code flow with the longjmp(). It could cause memory leaks or leaves GDAL in an unstable state (unreleased locks, or whatever). What would be safer would be that the error handler just stores the error code and/or message, and just looks at it after the return from the GDAL code. Something like this : static CPLErr saved_eErrClass = CE_None; static saved_err_no = 0; static char saved_error_msg[2048]; static void __errorHandler(CPLErr eErrClass, int err_no, const char *msg) { saved_eErrClass = eErrClass; saved_err_no = err_no; /* a mutex could be usefull here to avoid a race condition if 2 threads trigger the error handler at the same time */ strncpy(saved_error_msg, msg, sizeof(saved_error_msg)); saved_error_msg[sizeof(saved_error_msg)-1] = 0; } void installErrorHandler() { CPLPushErrorHandler(__errorHandler); saved_err_no = 0; } void uninstallErrorHandlerAndTriggerRError() { CPLPopErrorHandler(); if (saved_err_no == CE_Warning) { warning("\n\tNon-fatal GDAL Error %d: %s\n", saved_err_no, saved_error_msg); } else if (saved_err_no == CE_Failure) { error("\n\tGDAL Error %d: %s\n", saved_err_no, saved_error_msg); } } SEXP RGDAL_GetDescription(SEXP sxpObj) { void *pGDALObj = getGDALObjPtr(sxpObj); installErrorHandler(); const char *desc = ((GDALMajorObject *)pGDALObj)->GetDescription(); uninstallErrorHandlerAndTriggerRError(); return(mkString_safe(desc)); } Or you could also take the approach of gdal/swig/include/python/python_exceptions.i where the installed error handler just forwards CE_Fatal, CE_Warning and CE_Debug to the previous error handler (or the default one if there's none). After the GDAL call, it just looks at CPLGetLastErrorType() and if it is CE_Failure, it triggers a Python exception with the error messages fetched with CPLGetLastErrorMsg(). Something like http://trac.osgeo.org/qgis/browser/trunk/qgis/src/providers/ogr/qgsogrprovid er.cpp#L67 might be useful to automate the push/pop. R-Forge SVN README This file explains the repository structure of your project. A more detailed guide to R-Forge is available by Theußl and Zeileis (2010) [1] and the R-Forge Administration and Development Team (2009) [2]. 1. Introduction ----------------------------------------------------------------------- R is free software distributed under a GNU-style copyleft. R-Forge is a central platform for the development of R packages, R-related software and further projects. Among many other web-based features it provides facilities for collaborative source code management via Subversion (SVN) [3]. 2. The directory you're in ----------------------------------------------------------------------- This is the repository of your project. It contains two important pre-defined directories namely 'pkg' and 'www'. These directories must not be deleted otherwise R-Forge's core functionality will not be available (i.e., daily checking and building of your package or the project websites). 'pkg' and 'www' are standardized and therefore are going to be described in this README. The rest of your repository can be used as you like. 3. 'pkg' directory ----------------------------------------------------------------------- To make use of the package building and checking feature the package source code has to be put into the 'pkg' directory of your repository (i.e., 'pkg/DESCRIPTION', 'pkg/R', 'pkg/man', etc.) or, alternatively, a subdirectory of 'pkg'. The latter structure allows for having more than one package in a single project, e.g., if a project consists of the packages foo and bar then the source code will be located in 'pkg/foo' and 'pkg/bar', respectively. R-Forge automatically examines the 'pkg' directory of every repository and builds the package sources as well as the package binaries on a daily basis for Mac OS X and Windows (if applicable). The package builds are provided in the 'R Packages' tab for download or can be installed directly in R from a CRAN-style repository using 'install.packages("foo", repos="http://R-Forge.R-project.org")'. Furthermore, in the 'R Packages' tab developers can examine logs generated on different platforms by the build and check process. 4. 'www' directory ----------------------------------------------------------------------- Developers may present their project on a subdomain of R-Forge, e.g., 'http://foo.R-Forge.R-project.org', or via a link to an external website. This directory contains the project homepage which gets updated hourly on R-Forge, so please take into consideration that it will not be available right after you commit your changes or additions. 5. Help ----------------------------------------------------------------------- If you need help don't hesitate to submit a support request at https://r-forge.r-project.org/tracker/?func=add&group_id=34&atid=194, search the forum https://r-forge.r-project.org/forum/forum.php?forum_id=78&group_id=34, or contact us at [email protected]. 6. References ----------------------------------------------------------------------- [1] Stefan Theußl and Achim Zeileis. Collaborative software development using R-Forge. The R Journal, 1(1):9-14, May 2009. URL http://journal.r-project.org/2009-1/RJournal_2009-1_Theussl+Zeileis.pdf [2] R-Forge Administration and Development Team. RForge User’s Manual, 2008. URL http://download.R-Forge.R-project.org/R-Forge.pdf [3] C. M. Pilato, B. Collins-Sussman, and B. W. Fitzpatrick. Version Control with Subversion. O’Reilly, 2004. Full book available online at http://svnbook.red-bean.com/
About
Read-only mirror of "rgdal" from r-forge SVN.
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published