-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
223 lines (171 loc) · 7.97 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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/