Skip to content

Commit 9f96285

Browse files
authored
win32/signal.c: convert ctrl_handler to FCC (#22210)
1 parent b5c17e7 commit 9f96285

2 files changed

Lines changed: 55 additions & 17 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
sapi_windows_set_ctrl_handler() trampoline test
3+
--SKIPIF--
4+
<?php
5+
include "skipif.inc";
6+
7+
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
8+
die("skip this test is for Windows platforms only");
9+
?>
10+
--FILE--
11+
<?php
12+
13+
class TrampolineTest {
14+
public function __call(string $name, array $arguments) {
15+
echo 'Trampoline for ', $name, PHP_EOL;
16+
}
17+
}
18+
$o = new TrampolineTest();
19+
$callback = [$o, 'trampoline'];
20+
21+
sapi_windows_set_ctrl_handler($callback);
22+
23+
function foo(int $event) { }
24+
25+
sapi_windows_set_ctrl_handler(foo(...));
26+
27+
echo "Done\n";
28+
29+
?>
30+
--EXPECT--
31+
Done

win32/signal.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,20 @@
1818
#include "win32/console.h"
1919

2020
/* true globals; only used from main thread and from kernel callback */
21-
static zval ctrl_handler;
21+
static zend_fcall_info_cache ctrl_handler;
2222
static DWORD ctrl_evt = (DWORD)-1;
2323
static zend_atomic_bool *vm_interrupt_flag = NULL;
2424

2525
static void (*orig_interrupt_function)(zend_execute_data *execute_data);
2626

2727
static void php_win32_signal_ctrl_interrupt_function(zend_execute_data *execute_data)
2828
{/*{{{*/
29-
if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
30-
zval retval, params[1];
29+
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
30+
zval params[1];
3131

3232
ZVAL_LONG(&params[0], ctrl_evt);
3333

34-
/* If the function returns, */
35-
call_user_function(NULL, NULL, &ctrl_handler, &retval, 1, params);
36-
zval_ptr_dtor(&retval);
34+
zend_call_known_fcc(&ctrl_handler, NULL, 1, params, NULL);
3735
}
3836

3937
if (orig_interrupt_function) {
@@ -51,7 +49,7 @@ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_init(void)
5149
orig_interrupt_function = zend_interrupt_function;
5250
zend_interrupt_function = php_win32_signal_ctrl_interrupt_function;
5351
vm_interrupt_flag = &EG(vm_interrupt);
54-
ZVAL_UNDEF(&ctrl_handler);
52+
ctrl_handler = empty_fcall_info_cache;
5553

5654
REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_C", CTRL_C_EVENT, CONST_PERSISTENT);
5755
REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_BREAK", CTRL_BREAK_EVENT, CONST_PERSISTENT);
@@ -82,9 +80,8 @@ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_request_shutdown(void)
8280

8381
/* The ctrl_handler must be cleared between requests, otherwise we can crash
8482
* due to accessing a previous request's memory. */
85-
if (!Z_ISUNDEF(ctrl_handler)) {
86-
zval_ptr_dtor(&ctrl_handler);
87-
ZVAL_UNDEF(&ctrl_handler);
83+
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
84+
zend_fcc_dtor(&ctrl_handler);
8885
}
8986
}
9087

@@ -110,37 +107,47 @@ PHP_FUNCTION(sapi_windows_set_ctrl_handler)
110107

111108

112109
/* callable argument corresponds to the CTRL handler */
113-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!|b", &fci, &fcc, &add) == FAILURE) {
110+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "F!|b", &fci, &fcc, &add) == FAILURE) {
114111
RETURN_THROWS();
115112
}
116113

117114
#ifdef ZTS
118115
if (!tsrm_is_main_thread()) {
116+
if (ZEND_FCC_INITIALIZED(fcc)) {
117+
zend_release_fcall_info_cache(&fcc);
118+
}
119119
zend_throw_error(NULL, "CTRL events can only be received on the main thread");
120120
RETURN_THROWS();
121121
}
122122
#endif
123123

124124
if (!php_win32_console_is_cli_sapi()) {
125+
if (ZEND_FCC_INITIALIZED(fcc)) {
126+
zend_release_fcall_info_cache(&fcc);
127+
}
125128
zend_throw_error(NULL, "CTRL events trapping is only supported on console");
126129
RETURN_THROWS();
127130
}
128131

129-
if (!ZEND_FCI_INITIALIZED(fci)) {
130-
zval_ptr_dtor(&ctrl_handler);
131-
ZVAL_UNDEF(&ctrl_handler);
132+
if (!ZEND_FCC_INITIALIZED(fcc)) {
133+
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
134+
zend_fcc_dtor(&ctrl_handler);
135+
}
132136
RETURN_BOOL(SetConsoleCtrlHandler(NULL, add));
133137
}
134138

135139
if (!SetConsoleCtrlHandler(NULL, FALSE) || !SetConsoleCtrlHandler(php_win32_signal_system_ctrl_handler, add)) {
136140
zend_string *func_name = zend_get_callable_name(&fci.function_name);
137141
php_error_docref(NULL, E_WARNING, "Unable to attach %s as a CTRL handler", ZSTR_VAL(func_name));
138142
zend_string_release_ex(func_name, 0);
143+
zend_release_fcall_info_cache(&fcc);
139144
RETURN_FALSE;
140145
}
141146

142-
zval_ptr_dtor(&ctrl_handler);
143-
ZVAL_COPY(&ctrl_handler, &fci.function_name);
147+
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
148+
zend_fcc_dtor(&ctrl_handler);
149+
}
150+
zend_fcc_dup(&ctrl_handler, &fcc);
144151

145152
RETURN_TRUE;
146153
}/*}}}*/
@@ -163,7 +170,7 @@ PHP_FUNCTION(sapi_windows_generate_ctrl_event)
163170

164171
ret = (GenerateConsoleCtrlEvent(evt, pid) != 0);
165172

166-
if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
173+
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
167174
ret = ret && SetConsoleCtrlHandler(php_win32_signal_system_ctrl_handler, TRUE);
168175
}
169176

0 commit comments

Comments
 (0)