Skip to content
/ rgdal Public

Read-only mirror of "rgdal" from r-forge SVN.

Notifications You must be signed in to change notification settings

r-forge/rgdal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

No packages published