Skip to content

Commit 88dbc85

Browse files
committed
Port PR #3490
1 parent 8716885 commit 88dbc85

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
Bailout during hook END should not cause double-clear of span (internal function)
3+
--SKIPIF--
4+
<?php if (PHP_VERSION_ID >= 80000) die('skip: PHP 7 only'); ?>
5+
--FILE--
6+
<?php
7+
8+
DDTrace\trace_function('array_sum', [
9+
'prehook' => function (\DDTrace\SpanData $data, $args) {
10+
echo "HOOK 1 PRE\n";
11+
},
12+
'posthook' => function(\DDTrace\SpanData $span, $args, $retval) {
13+
static $ba = true;
14+
echo "Hook 1 END\n";
15+
if ($ba) {
16+
echo "WILL BAILOUT!\n";
17+
}
18+
trigger_error("Datadog blocked the request", E_USER_ERROR);
19+
}
20+
]);
21+
22+
DDTrace\trace_function('array_sum', [
23+
'posthook' => function(\DDTrace\SpanData $data, $args, $retval) {
24+
echo "Hook 2 END\n";
25+
}
26+
]);
27+
28+
register_shutdown_function(function() {
29+
echo "Shutdown function executed\n";
30+
});
31+
32+
echo "Calling array_sum\n";
33+
array_sum([1, 2, 3]);
34+
echo "After array_sum (should not print)\n";
35+
36+
?>
37+
--EXPECTF--
38+
Calling array_sum
39+
HOOK 1 PRE
40+
Hook 2 END
41+
Hook 1 END
42+
WILL BAILOUT!
43+
Shutdown function executed

zend_abstract_interface/hook/hook.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,12 @@ void zai_hook_finish(zend_execute_data *ex, zval *rv, zai_hook_memory_t *memory)
11121112
for (zai_hook_info *hook_start = memory->dynamic, *hook_info = hook_start + memory->hook_count - 1; hook_info >= hook_start; --hook_info) {
11131113
zai_hook_t *hook = hook_info->hook;
11141114

1115+
// if we propagate bailout during hook->end, we don't try to finish
1116+
// again in zai_interceptor_terminate_all_pending_observers
1117+
// This may even segfault due to too many calls to
1118+
// ddtrace_clear_execute_data_span
1119+
memory->hook_count--;
1120+
11151121
if (hook->end) {
11161122
hook->end(memory->invocation, ex, rv, hook->aux.data, (char *)memory->dynamic + hook_info->dynamic_offset);
11171123
}

zend_abstract_interface/interceptor/php7/interceptor.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ typedef struct {
6767
ZEND_TLS HashTable zai_hook_memory;
6868
// execute_data is 16 byte aligned (except when it isn't, but it doesn't matter as zend_execute_data is big enough
6969
// our goal is to reduce conflicts
70-
static inline void zai_hook_memory_table_insert(zend_execute_data *index, zai_interceptor_frame_memory *inserting) {
71-
zend_hash_index_update_mem(&zai_hook_memory, ((zend_ulong)index) >> 4, inserting, sizeof(*inserting));
70+
static inline zai_interceptor_frame_memory *zai_hook_memory_table_insert(zend_execute_data *index, zai_interceptor_frame_memory *inserting) {
71+
return zend_hash_index_update_mem(&zai_hook_memory, ((zend_ulong)index) >> 4, inserting, sizeof(*inserting));
7272
}
7373

7474
static inline void *zai_hook_memory_table_insert_generator(zend_execute_data *index, zai_interceptor_generator_frame_memory *inserting) {
@@ -497,7 +497,7 @@ static inline void zai_interceptor_execute_internal_impl(zend_execute_data *exec
497497
}
498498
frame_memory.execute_data = execute_data;
499499
frame_memory.implicit = false;
500-
zai_hook_memory_table_insert(execute_data, &frame_memory);
500+
zai_interceptor_frame_memory *stored_frame_memory = zai_hook_memory_table_insert(execute_data, &frame_memory);
501501

502502
// we do not use try / catch here as to preserve order of hooks, LIFO style, in bailout handler
503503
if (prev) {
@@ -506,7 +506,7 @@ static inline void zai_interceptor_execute_internal_impl(zend_execute_data *exec
506506
func->internal_function.handler(execute_data, return_value);
507507
}
508508

509-
zai_hook_finish(execute_data, return_value, &frame_memory.hook_data);
509+
zai_hook_finish(execute_data, return_value, &stored_frame_memory->hook_data);
510510
zai_hook_memory_table_del(execute_data);
511511
} else {
512512
skip: ;

0 commit comments

Comments
 (0)