Commit 7a66ef9
fix(tracing): intern process_tags.serialized to avoid ZTS refcount race (#3831)
* fix(tracing): treat process_tags.serialized as interned to avoid ZTS refcount race
ext/process_tags.c stores a single process-wide zend_string at first-request
init (zend_string_init persistent=1) and shares it across all ZTS threads.
Every span serialization on a first-span path passes that pointer to Rust,
which calls back into PHP's zend_string_addref/zend_string_release through
ddog_init_span_func to manage a refcount on its Bytes wrapper. Those ops are
non-atomic ++/-- on a single shared field; under FrankenPHP + PHP 8.4 ZTS
with concurrent worker threads at load, the races produce torn refcount
values, premature frees, and use-after-free reads of process_tags.serialized
during convert_zend_to_bytes_string -> String::from_utf8_lossy, surfacing as
SIGSEGV / SIGABRT / "memory allocation of <huge> bytes failed" / glibc
"double free or corruption".
Mark the string IS_STR_INTERNED (= GC_IMMUTABLE) on creation so the refcount
helpers see it as immutable and skip the ++/--.Clear
the flag in clear_process_tags before the release so the persistent
allocation is actually freed at module shutdown.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* fix(tracing): precompute hash on process_tags.serialized before marking interned
Interned zend_strings are expected to have h pre-populated (callers may read
ZSTR_H(s) raw). zend_string_init leaves h zero, so setting IS_STR_INTERNED
without computing the hash leaves any hash-keyed lookup broken. Force the
compute via zend_string_hash_val() before adding the flag.
Squashable with the previous fix commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Remove unnecessary callback
* Adjust comments
---------
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Co-authored-by: Bob Weinand <[email protected]>1 parent 96e825a commit 7a66ef9
1 file changed
Lines changed: 5 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
| 59 | + | |
58 | 60 | | |
59 | 61 | | |
60 | 62 | | |
| |||
255 | 257 | | |
256 | 258 | | |
257 | 259 | | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
258 | 263 | | |
259 | 264 | | |
260 | 265 | | |
| |||
0 commit comments