[Proj] PROJ.4 thread-safety issues detailed
Patrick Mézard
pmezard at gmail.com
Mon Feb 28 13:20:43 EST 2005
Hello,
I have looked for static variables in PROJ.4 code and found the
following potential problems :
1-rtodms.c:
RES, RES60, CONV, format, do_long are non-const globals.
2- pj_strerrno.c:
note is static in pj_strerrno.
3- pj_open_lib.c :
pj_finder, path_count, search_path are non-const globals.
4- pj_init.c
start is a non-const global.
5- Many globals in grid stuff. Not listed
6- Some globals in geodesic stuff. Not listed.
7- Many globals in projection approximation code. Not listed.
My point of view :
- Evidently, everything (related to globals) can be solved by using
thread-local storage.
- I do not use 1, 5, 6, 7 and I will not try to edit them. 1 can be
changed easily by adding a format description structure to function
calls.
- 2 is like the problem with pj_errno, and I will solve it with
thread-local storage. It is hard to code something else without using
callbacks or allocating memory which would make the whole think much
more complicated to use.
- 3 is used in pj_init. I do not use this feature, and I will just
disable the +init and default parameters options.
- 4 is critical but easily corrected by changing start into a local
variable and passing it to every other function. See the attached
patch.
Hope this helps.
Patrick Mézard
-------------- next part --------------
*** proj.4-prev\src\pj_init.c Wed Sep 08 11:23:38 2004
--- proj.4\src\pj_init.c Mon Feb 28 19:14:48 2005
***************
*** 68,81 ****
PJ_CVSID("$Id: pj_init.c,v 1.16 2004/09/08 15:23:37 warmerda Exp $");
- static paralist *start;
extern FILE *pj_open_lib(char *, char *);
/************************************************************************/
/* get_opt() */
/************************************************************************/
static paralist *
! get_opt(FILE *fid, char *name, paralist *next) {
char sword[302], *word = sword+1;
int first = 1, len, c;
--- 68,80 ----
PJ_CVSID("$Id: pj_init.c,v 1.16 2004/09/08 15:23:37 warmerda Exp $");
extern FILE *pj_open_lib(char *, char *);
/************************************************************************/
/* get_opt() */
/************************************************************************/
static paralist *
! get_opt(FILE *fid, char *name, paralist *start, paralist *next) {
char sword[302], *word = sword+1;
int first = 1, len, c;
***************
*** 117,129 ****
/* get_defaults() */
/************************************************************************/
static paralist *
! get_defaults(paralist *next, char *name) {
FILE *fid;
if (fid = pj_open_lib("proj_def.dat", "rt")) {
! next = get_opt(fid, "general", next);
rewind(fid);
! next = get_opt(fid, name, next);
(void)fclose(fid);
}
if (errno)
--- 116,128 ----
/* get_defaults() */
/************************************************************************/
static paralist *
! get_defaults(paralist *start, paralist *next, char *name) {
FILE *fid;
if (fid = pj_open_lib("proj_def.dat", "rt")) {
! next = get_opt(fid, "general", start, next);
rewind(fid);
! next = get_opt(fid, name, start, next);
(void)fclose(fid);
}
if (errno)
***************
*** 135,141 ****
/* get_init() */
/************************************************************************/
static paralist *
! get_init(paralist *next, char *name) {
char fname[MAX_PATH_FILENAME+ID_TAG_MAX+3], *opt;
FILE *fid;
--- 134,140 ----
/* get_init() */
/************************************************************************/
static paralist *
! get_init(paralist *start, paralist *next, char *name) {
char fname[MAX_PATH_FILENAME+ID_TAG_MAX+3], *opt;
FILE *fid;
***************
*** 144,150 ****
*opt++ = '\0';
else { pj_errno = -3; return(0); }
if (fid = pj_open_lib(fname, "rt"))
! next = get_opt(fid, opt, next);
else
return(0);
(void)fclose(fid);
--- 143,149 ----
*opt++ = '\0';
else { pj_errno = -3; return(0); }
if (fid = pj_open_lib(fname, "rt"))
! next = get_opt(fid, opt, start, next);
else
return(0);
(void)fclose(fid);
***************
*** 226,237 ****
pj_init(int argc, char **argv) {
char *s, *name;
PJ *(*proj)(PJ *);
! paralist *curr;
int i;
PJ *PIN = 0;
errno = pj_errno = 0;
- start = NULL;
/* put arguments into internal linked list */
if (argc <= 0) { pj_errno = -1; goto bum_call; }
--- 225,236 ----
pj_init(int argc, char **argv) {
char *s, *name;
PJ *(*proj)(PJ *);
! paralist *curr = 0;
int i;
PJ *PIN = 0;
+ paralist* start = NULL;
errno = pj_errno = 0;
/* put arguments into internal linked list */
if (argc <= 0) { pj_errno = -1; goto bum_call; }
***************
*** 246,252 ****
if (pj_param(start, "tinit").i) {
paralist *last = curr;
! if (!(curr = get_init(curr, pj_param(start, "sinit").s)))
goto bum_call;
if (curr == last) { pj_errno = -2; goto bum_call; }
}
--- 245,251 ----
if (pj_param(start, "tinit").i) {
paralist *last = curr;
! if (!(curr = get_init(start, curr, pj_param(start, "sinit").s)))
goto bum_call;
if (curr == last) { pj_errno = -2; goto bum_call; }
}
***************
*** 259,265 ****
/* set defaults, unless inhibited */
if (!pj_param(start, "bno_defs").i)
! curr = get_defaults(curr, name);
proj = (PJ *(*)(PJ *)) pj_list[i].proj;
/* allocate projection structure */
--- 258,264 ----
/* set defaults, unless inhibited */
if (!pj_param(start, "bno_defs").i)
! curr = get_defaults(start, curr, name);
proj = (PJ *(*)(PJ *)) pj_list[i].proj;
/* allocate projection structure */
More information about the Proj
mailing list