php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
signal.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Anatol Belski <ab@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17#include "php.h"
18#include "SAPI.h"
19
20#include "win32/console.h"
21
22/* true globals; only used from main thread and from kernel callback */
23static zval ctrl_handler;
24static DWORD ctrl_evt = (DWORD)-1;
25static zend_atomic_bool *vm_interrupt_flag = NULL;
26
27static void (*orig_interrupt_function)(zend_execute_data *execute_data);
28
29static void php_win32_signal_ctrl_interrupt_function(zend_execute_data *execute_data)
30{/*{{{*/
31 if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
32 zval retval, params[1];
33
34 ZVAL_LONG(&params[0], ctrl_evt);
35
36 /* If the function returns, */
37 call_user_function(NULL, NULL, &ctrl_handler, &retval, 1, params);
39 }
40
41 if (orig_interrupt_function) {
42 orig_interrupt_function(execute_data);
43 }
44}/*}}}*/
45
47{/*{{{*/
48 /* We are in the main thread! */
50 return;
51 }
52
53 orig_interrupt_function = zend_interrupt_function;
54 zend_interrupt_function = php_win32_signal_ctrl_interrupt_function;
55 vm_interrupt_flag = &EG(vm_interrupt);
56 ZVAL_UNDEF(&ctrl_handler);
57
58 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_C", CTRL_C_EVENT, CONST_PERSISTENT);
59 REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_BREAK", CTRL_BREAK_EVENT, CONST_PERSISTENT);
60}/*}}}*/
61
63{/*{{{*/
65 return;
66 }
67
68 zend_interrupt_function = orig_interrupt_function;
69 orig_interrupt_function = NULL;
70 vm_interrupt_flag = NULL;
71}/*}}}*/
72
74{
75 /* Must be initialized and in main thread */
76 if (!vm_interrupt_flag) {
77 return;
78 }
79#ifdef ZTS
80 if (!tsrm_is_main_thread()) {
81 return;
82 }
83#endif
84
85 /* The ctrl_handler must be cleared between requests, otherwise we can crash
86 * due to accessing a previous request's memory. */
87 if (!Z_ISUNDEF(ctrl_handler)) {
88 zval_ptr_dtor(&ctrl_handler);
89 ZVAL_UNDEF(&ctrl_handler);
90 }
91}
92
93static BOOL WINAPI php_win32_signal_system_ctrl_handler(DWORD evt)
94{/*{{{*/
95 if (CTRL_C_EVENT != evt && CTRL_BREAK_EVENT != evt) {
96 return FALSE;
97 }
98
99 zend_atomic_bool_store_ex(vm_interrupt_flag, true);
100
101 ctrl_evt = evt;
102
103 return TRUE;
104}/*}}}*/
105
106/* {{{ Assigns a CTRL signal handler to a PHP function */
108{
109 zend_fcall_info fci;
111 bool add = 1;
112
113
114 /* callable argument corresponds to the CTRL handler */
115 if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!|b", &fci, &fcc, &add) == FAILURE) {
117 }
118
119#ifdef ZTS
120 if (!tsrm_is_main_thread()) {
121 zend_throw_error(NULL, "CTRL events can only be received on the main thread");
123 }
124#endif
125
127 zend_throw_error(NULL, "CTRL events trapping is only supported on console");
129 }
130
131 if (!ZEND_FCI_INITIALIZED(fci)) {
132 zval_ptr_dtor(&ctrl_handler);
133 ZVAL_UNDEF(&ctrl_handler);
134 if (!SetConsoleCtrlHandler(NULL, add)) {
136 }
138 }
139
140 if (!SetConsoleCtrlHandler(NULL, FALSE) || !SetConsoleCtrlHandler(php_win32_signal_system_ctrl_handler, add)) {
142 php_error_docref(NULL, E_WARNING, "Unable to attach %s as a CTRL handler", ZSTR_VAL(func_name));
145 }
146
147 zval_ptr_dtor(&ctrl_handler);
148 ZVAL_COPY(&ctrl_handler, &fci.function_name);
149
151}/*}}}*/
152
154{/*{{{*/
155 zend_long evt, pid = 0;
156 bool ret = 0;
157
158 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &evt, &pid) == FAILURE) {
160 }
161
163 zend_throw_error(NULL, "CTRL events trapping is only supported on console");
164 return;
165 }
166
167 SetConsoleCtrlHandler(NULL, TRUE);
168
169 ret = (GenerateConsoleCtrlEvent(evt, pid) != 0);
170
171 if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
172 ret = ret && SetConsoleCtrlHandler(php_win32_signal_system_ctrl_handler, TRUE);
173 }
174
176}/*}}}*/
sapi_windows_generate_ctrl_event(int $event, int $pid=0)
sapi_windows_set_ctrl_handler(?callable $handler, bool $add=true)
PHP_WINUTIL_API BOOL php_win32_console_is_cli_sapi(void)
Definition console.c:112
#define PHP_WINUTIL_API
Definition console.h:24
#define DWORD
Definition exif.c:1762
#define TRUE
Definition gd_gd.c:7
#define FALSE
Definition gd_gd.c:8
#define NULL
Definition gdcache.h:45
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
int BOOL
#define PHP_FUNCTION
Definition php.h:364
#define add(i, ts)
const char * func_name
PHP_WINUTIL_API void php_win32_signal_ctrl_handler_request_shutdown(void)
Definition signal.c:73
PHP_WINUTIL_API void php_win32_signal_ctrl_handler_init(void)
Definition signal.c:46
PHP_WINUTIL_API void php_win32_signal_ctrl_handler_shutdown(void)
Definition signal.c:62
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API void(* zend_interrupt_function)(zend_execute_data *execute_data)
Definition zend.c:89
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API zend_string * zend_get_callable_name(zval *callable)
Definition zend_API.c:4154
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
struct _zend_fcall_info_cache zend_fcall_info_cache
#define RETURN_FALSE
Definition zend_API.h:1058
#define ZEND_FCI_INITIALIZED(fci)
Definition zend_API.h:340
#define RETURN_BOOL(b)
Definition zend_API.h:1035
struct _zend_fcall_info zend_fcall_info
#define RETURN_THROWS()
Definition zend_API.h:1060
#define call_user_function(function_table, object, function_name, retval_ptr, param_count, params)
Definition zend_API.h:687
#define RETURN_TRUE
Definition zend_API.h:1059
struct zend_atomic_bool_s zend_atomic_bool
struct _zval_struct zval
zend_string_release_ex(func->internal_function.function_name, 0)
#define CONST_PERSISTENT
#define REGISTER_MAIN_LONG_CONSTANT(name, lval, flags)
#define E_WARNING
Definition zend_errors.h:24
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define EG(v)
int32_t zend_long
Definition zend_long.h:42
struct _zend_string zend_string
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZVAL_UNDEF(z)
#define IS_UNDEF
Definition zend_types.h:600
#define ZVAL_LONG(z, l)
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
@ FAILURE
Definition zend_types.h:61
#define ZVAL_COPY(z, v)
#define Z_TYPE(zval)
Definition zend_types.h:659
struct _zend_execute_data zend_execute_data
Definition zend_types.h:91
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
execute_data
zval * ret