Skip to content

Commit 8d0cf27

Browse files
morrisonlevibwoebi
andauthored
fix(prof): crash on PHP 8.4 (#3019)
* fix: register internal run time cache handles separately On PHP 8.4, the cache slots for internal and userland functions are separate. --------- Signed-off-by: Bob Weinand <[email protected]> Co-authored-by: Bob Weinand <[email protected]>
1 parent 7d37019 commit 8d0cf27

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

profiling/src/php_ffi.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,14 @@ zend_fiber* ddog_php_prof_get_active_fiber_test()
315315
#endif
316316

317317
#if CFG_RUN_TIME_CACHE // defined by build.rs
318-
static int ddog_php_prof_run_time_cache_handle = -1;
318+
static int _user_run_time_cache_handle = -1;
319+
320+
// On PHP 8.4+, the internal cache slots need to be registered separately from
321+
// the user ones.
322+
#if PHP_VERSION_ID >= 80400
323+
static int _internal_run_time_cache_handle = -1;
324+
#endif
325+
319326
#endif
320327

321328
void ddog_php_prof_function_run_time_cache_init(const char *module_name) {
@@ -324,13 +331,21 @@ void ddog_php_prof_function_run_time_cache_init(const char *module_name) {
324331
// Grab 1 slot for caching filename, as it turns out the utf-8 validity
325332
// check is worth caching.
326333
#if PHP_VERSION_ID < 80200
327-
ddog_php_prof_run_time_cache_handle =
334+
_user_run_time_cache_handle =
328335
zend_get_op_array_extension_handle(module_name);
329336
int second = zend_get_op_array_extension_handle(module_name);
330-
ZEND_ASSERT(ddog_php_prof_run_time_cache_handle + 1 == second);
337+
ZEND_ASSERT(_user_run_time_cache_handle + 1 == second);
331338
#else
332-
ddog_php_prof_run_time_cache_handle =
339+
_user_run_time_cache_handle =
333340
zend_get_op_array_extension_handles(module_name, 2);
341+
342+
#if PHP_VERSION_ID >= 80400
343+
// On PHP 8.4+, the internal cache slots need to be registered separately
344+
// from the user ones.
345+
_internal_run_time_cache_handle =
346+
zend_get_internal_function_extension_handles(module_name, 2);
347+
#endif
348+
334349
#endif
335350
#else
336351
(void)module_name;
@@ -346,7 +361,21 @@ void ddog_php_prof_function_run_time_cache_init(const char *module_name) {
346361
// defined by build.rs
347362
#if CFG_RUN_TIME_CACHE && !CFG_STACK_WALKING_TESTS
348363
static bool has_invalid_run_time_cache(zend_function const *func) {
349-
if (UNEXPECTED(_ignore_run_time_cache) || UNEXPECTED(ddog_php_prof_run_time_cache_handle < 0))
364+
bool ignore_cache = _ignore_run_time_cache;
365+
bool inv_user_handle = _user_run_time_cache_handle < 0;
366+
367+
// The bitwise-ors are intentional here. We don't expect any of these
368+
// things to be true, except if we're on CLI and in that case it's okay
369+
// to pessimize since it'll predict well after it gets it wrong the first
370+
// time.
371+
#if PHP_VERSION_ID < 80400
372+
bool fast_skip = ignore_cache | inv_user_handle;
373+
#else
374+
bool inv_internal_handle = _internal_run_time_cache_handle < 0;
375+
bool fast_skip = ignore_cache | inv_user_handle | inv_internal_handle;
376+
#endif
377+
378+
if (UNEXPECTED(fast_skip))
350379
return true;
351380

352381
// during an `include()`/`require()` with enabled OPcache, OPcache is
@@ -391,7 +420,14 @@ uintptr_t *ddog_php_prof_function_run_time_cache(zend_function const *func) {
391420
*/
392421
ZEND_ASSERT(cache_addr);
393422

394-
return cache_addr + ddog_php_prof_run_time_cache_handle;
423+
#if PHP_VERSION_ID < 80400
424+
int handle_offset = _user_run_time_cache_handle;
425+
#else
426+
int handle_offset = func->type == ZEND_USER_FUNCTION
427+
? _user_run_time_cache_handle
428+
: _internal_run_time_cache_handle;
429+
#endif
430+
return cache_addr + handle_offset;
395431

396432
#else
397433
(void)func;

0 commit comments

Comments
 (0)