Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Zend/zend_ini.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,11 @@ ZEND_API zend_string *zend_ini_get_value(zend_string *name) /* {{{ */

ZEND_API bool zend_ini_parse_bool(const zend_string *str)
{
/* May happen if an unknown INI setting is queried via zend_ini_bool_literal(),
* as zend_ini_str() would return NULL */
if (UNEXPECTED(str == NULL)) {
return false;
}
if (zend_string_equals_literal_ci(str, "true")
|| zend_string_equals_literal_ci(str, "yes")
|| zend_string_equals_literal_ci(str, "on")
Expand Down
31 changes: 31 additions & 0 deletions sapi/cli/tests/sapi_windows_set_ctrl_trampoline.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
--TEST--
sapi_windows_set_ctrl_handler() trampoline test
--SKIPIF--
<?php
include "skipif.inc";

if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
die("skip this test is for Windows platforms only");
?>
--FILE--
<?php

class TrampolineTest {
public function __call(string $name, array $arguments) {
echo 'Trampoline for ', $name, PHP_EOL;
}
}
$o = new TrampolineTest();
$callback = [$o, 'trampoline'];

sapi_windows_set_ctrl_handler($callback);

function foo(int $event) { }

sapi_windows_set_ctrl_handler(foo(...));

echo "Done\n";

?>
--EXPECT--
Done
41 changes: 24 additions & 17 deletions win32/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,20 @@
#include "win32/console.h"

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

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

static void php_win32_signal_ctrl_interrupt_function(zend_execute_data *execute_data)
{/*{{{*/
if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
zval retval, params[1];
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
zval params[1];

ZVAL_LONG(&params[0], ctrl_evt);

/* If the function returns, */
call_user_function(NULL, NULL, &ctrl_handler, &retval, 1, params);
zval_ptr_dtor(&retval);
zend_call_known_fcc(&ctrl_handler, NULL, 1, params, NULL);
}

if (orig_interrupt_function) {
Expand All @@ -51,7 +49,7 @@ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_init(void)
orig_interrupt_function = zend_interrupt_function;
zend_interrupt_function = php_win32_signal_ctrl_interrupt_function;
vm_interrupt_flag = &EG(vm_interrupt);
ZVAL_UNDEF(&ctrl_handler);
ctrl_handler = empty_fcall_info_cache;

REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_C", CTRL_C_EVENT, CONST_PERSISTENT);
REGISTER_MAIN_LONG_CONSTANT("PHP_WINDOWS_EVENT_CTRL_BREAK", CTRL_BREAK_EVENT, CONST_PERSISTENT);
Expand Down Expand Up @@ -82,9 +80,8 @@ PHP_WINUTIL_API void php_win32_signal_ctrl_handler_request_shutdown(void)

/* The ctrl_handler must be cleared between requests, otherwise we can crash
* due to accessing a previous request's memory. */
if (!Z_ISUNDEF(ctrl_handler)) {
zval_ptr_dtor(&ctrl_handler);
ZVAL_UNDEF(&ctrl_handler);
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
zend_fcc_dtor(&ctrl_handler);
}
}

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


/* callable argument corresponds to the CTRL handler */
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!|b", &fci, &fcc, &add) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "F!|b", &fci, &fcc, &add) == FAILURE) {
RETURN_THROWS();
}

#ifdef ZTS
if (!tsrm_is_main_thread()) {
if (ZEND_FCC_INITIALIZED(fcc)) {
zend_release_fcall_info_cache(&fcc);
}
zend_throw_error(NULL, "CTRL events can only be received on the main thread");
RETURN_THROWS();
}
#endif

if (!php_win32_console_is_cli_sapi()) {
if (ZEND_FCC_INITIALIZED(fcc)) {
zend_release_fcall_info_cache(&fcc);
}
zend_throw_error(NULL, "CTRL events trapping is only supported on console");
RETURN_THROWS();
}

if (!ZEND_FCI_INITIALIZED(fci)) {
zval_ptr_dtor(&ctrl_handler);
ZVAL_UNDEF(&ctrl_handler);
if (!ZEND_FCC_INITIALIZED(fcc)) {
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
zend_fcc_dtor(&ctrl_handler);
}
RETURN_BOOL(SetConsoleCtrlHandler(NULL, add));
}

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

zval_ptr_dtor(&ctrl_handler);
ZVAL_COPY(&ctrl_handler, &fci.function_name);
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
zend_fcc_dtor(&ctrl_handler);
}
zend_fcc_dup(&ctrl_handler, &fcc);

RETURN_TRUE;
}/*}}}*/
Expand All @@ -163,7 +170,7 @@ PHP_FUNCTION(sapi_windows_generate_ctrl_event)

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

if (IS_UNDEF != Z_TYPE(ctrl_handler)) {
if (ZEND_FCC_INITIALIZED(ctrl_handler)) {
ret = ret && SetConsoleCtrlHandler(php_win32_signal_system_ctrl_handler, TRUE);
}

Expand Down