Skip to content

lib/proj: fix data race on METERS_in/METERS_out in coordinate transform functions - #7764

Merged
echoix merged 1 commit into
OSGeo:mainfrom
krcoder123:fix-gproj-globals
Jul 25, 2026
Merged

lib/proj: fix data race on METERS_in/METERS_out in coordinate transform functions#7764
echoix merged 1 commit into
OSGeo:mainfrom
krcoder123:fix-gproj-globals

Conversation

@krcoder123

@krcoder123 krcoder123 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

This is the small separate PR for the globals fix suggested in the review of #7627.

GPJ_transform and three other functions in do_proj.c share two variables, METERS_in and METERS_out, that live at file scope. Every call writes into them. So if two threads call these functions at the same time, they both write into the same shared variables. This could cause a data race. It doesn't matter that each thread has its own cloned PJ object, because the race is on these shared variables and not on the PJ. In practice the output still came out correct since every thread happened to write the same values, but it is still undefined behavior and thread sanitizer found it.

The fix itself was pretty simple. Each of the four functions now has its own local copy of the two variables instead of sharing one pair at file scope. Each function already sets both values before using them, on every path through the code, so nothing about the output changes.

How I verified it:
I wrote a small test program where 8 threads call GPJ_transform at the same time, each thread with its own cloned PJ. On the old code, thread sanitizer reports data races on METERS_in and METERS_out in both transform directions. With this change, the same test runs clean in both directions. I also built r.proj with the change and its output is bit for bit identical to the unmodified module. I tested this with the nearest and bilinear methods.

The file-scope variables METERS_in and METERS_out were written on every
call to GPJ_transform, GPJ_transform_array, pj_do_proj, and
pj_do_transform. When GPJ_transform is called from multiple threads,
ThreadSanitizer reports data races on both variables even when each
thread uses its own cloned PJ object.

Each function writes both variables before reading them, so they carry
no state between calls. This change makes them locals of the four
functions and removes the file-scope declaration. Output is unchanged.
@echoix
echoix merged commit 7050369 into OSGeo:main Jul 25, 2026
28 checks passed
@github-actions github-actions Bot added this to the 8.6.0 milestone Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C Related code is in C libraries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants