From 60461ada51b8eb2d96b50b7dc0d65df1bc0a7a41 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 25 Feb 2026 19:36:26 +0000 Subject: [PATCH 1/2] ext/pcntl: use RETURN_THROWS() instead of RETURN_FALSE when exception is pending In pcntl_sigprocmask(), pcntl_sigwaitinfo(), and pcntl_sigtimedwait(). --- ext/pcntl/pcntl.c | 9 +++ .../pcntl_signal_functions_return_throws.phpt | 80 +++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 082bdc4ba90e8..08b9c98c11368 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -934,6 +934,9 @@ PHP_FUNCTION(pcntl_sigprocmask) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 2, /* allow_empty_signal_array */ how == SIG_SETMASK); /* Some error occurred */ if (!status) { + if (EG(exception)) { + RETURN_THROWS(); + } RETURN_FALSE; } @@ -982,6 +985,9 @@ PHP_FUNCTION(pcntl_sigwaitinfo) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false); /* Some error occurred */ if (!status) { + if (EG(exception)) { + RETURN_THROWS(); + } RETURN_FALSE; } @@ -1028,6 +1034,9 @@ PHP_FUNCTION(pcntl_sigtimedwait) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false); /* Some error occurred */ if (!status) { + if (EG(exception)) { + RETURN_THROWS(); + } RETURN_FALSE; } if (tv_sec < 0) { diff --git a/ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt b/ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt new file mode 100644 index 0000000000000..e61b17bf3fbd5 --- /dev/null +++ b/ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt @@ -0,0 +1,80 @@ +--TEST-- +pcntl_sigprocmask(), pcntl_sigwaitinfo(), and pcntl_sigtimedwait() properly throw on invalid signals +--EXTENSIONS-- +pcntl +--SKIPIF-- + +--INI-- +max_execution_time=0 +--FILE-- +getMessage() . PHP_EOL; +} + +try { + pcntl_sigprocmask(SIG_BLOCK, [0]); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigprocmask(SIG_BLOCK, []); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigwaitinfo(["not_a_signal"]); +} catch (TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigwaitinfo([0]); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigwaitinfo([]); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigtimedwait(["not_a_signal"], $info, 1); +} catch (TypeError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigtimedwait([0], $info, 1); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +try { + pcntl_sigtimedwait([], $info, 1); +} catch (ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + +?> +--EXPECTF-- +pcntl_sigprocmask(): Argument #2 ($signals) signals must be of type int, string given +pcntl_sigprocmask(): Argument #2 ($signals) signals must be between 1 and %d +pcntl_sigprocmask(): Argument #2 ($signals) must not be empty +pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be of type int, string given +pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be between 1 and %d +pcntl_sigwaitinfo(): Argument #1 ($signals) must not be empty +pcntl_sigtimedwait(): Argument #1 ($signals) signals must be of type int, string given +pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d +pcntl_sigtimedwait(): Argument #1 ($signals) must not be empty From 7336695b4e2b933b376cc4b188eb27506c7f46c1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 28 Feb 2026 13:46:39 +0000 Subject: [PATCH 2/2] ext/pcntl: drop unnecessary RETURN_THROWS() checks, keep test for invalid signals Revert the RETURN_THROWS() changes as RETURN_FALSE when an exception is pending is valid behaviour. Keep the test covering invalid signal handling for pcntl_sigprocmask(), pcntl_sigwaitinfo(), and pcntl_sigtimedwait(). --- ext/pcntl/pcntl.c | 9 --------- ....phpt => pcntl_signal_functions_invalid_signals.phpt} | 0 2 files changed, 9 deletions(-) rename ext/pcntl/tests/{pcntl_signal_functions_return_throws.phpt => pcntl_signal_functions_invalid_signals.phpt} (100%) diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 08b9c98c11368..082bdc4ba90e8 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -934,9 +934,6 @@ PHP_FUNCTION(pcntl_sigprocmask) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 2, /* allow_empty_signal_array */ how == SIG_SETMASK); /* Some error occurred */ if (!status) { - if (EG(exception)) { - RETURN_THROWS(); - } RETURN_FALSE; } @@ -985,9 +982,6 @@ PHP_FUNCTION(pcntl_sigwaitinfo) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false); /* Some error occurred */ if (!status) { - if (EG(exception)) { - RETURN_THROWS(); - } RETURN_FALSE; } @@ -1034,9 +1028,6 @@ PHP_FUNCTION(pcntl_sigtimedwait) bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false); /* Some error occurred */ if (!status) { - if (EG(exception)) { - RETURN_THROWS(); - } RETURN_FALSE; } if (tv_sec < 0) { diff --git a/ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt b/ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt similarity index 100% rename from ext/pcntl/tests/pcntl_signal_functions_return_throws.phpt rename to ext/pcntl/tests/pcntl_signal_functions_invalid_signals.phpt