mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
Refactor pcntl_sigprocmask()/pcntl_sigwaitinfo()/pcntl_sigtimedwait() (#11860)
This commit is contained in:
parent
d882c5d580
commit
1bdb0fddc1
16
UPGRADING
16
UPGRADING
@ -30,6 +30,22 @@ PHP 8.4 UPGRADE NOTES
|
||||
. The DSN's credentials, when set, are given priority over their PDO
|
||||
constructor counterparts, being closer to the documentation states.
|
||||
|
||||
- PCNTL:
|
||||
. The functions pcntl_sigprocmask(), pcntl_sigwaitinfo() and
|
||||
pcntl_sigtimedwait() now throw:
|
||||
- A ValueError if the $signals array is empty (except for
|
||||
pcntl_sigprocmask() if the $mode is SIG_SETMASK).
|
||||
- A TypeError if a value of the $signals array is not an integer
|
||||
- A ValueError if a value of the $signals array is not a valid signal number
|
||||
Moreover, those functions now always return false on failure.
|
||||
In some case previously it could return the value -1.
|
||||
. The function pcntl_sigprocmask() will also now throw:
|
||||
- A ValueError if $mode is not one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK
|
||||
. The function pcntl_sigtimedwait() will also now throw:
|
||||
- A ValueError if $seconds is less than 0
|
||||
- A ValueError if $nanoseconds is less than 0 or greater than 1e9
|
||||
- A ValueError if both $seconds and $nanoseconds are 0
|
||||
|
||||
- SimpleXML:
|
||||
. Get methods called, or casting to a string on a SimpleXMLElement will no
|
||||
longer implicitly reset the iterator data, unless explicitly rewound.
|
||||
|
@ -705,53 +705,107 @@ PHP_FUNCTION(pcntl_signal_dispatch)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Common helper function for these 3 wrapper functions */
|
||||
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) || defined(HAVE_SIGPROCMASK)
|
||||
static bool php_pcntl_set_user_signal_infos(
|
||||
/* const */ HashTable *const user_signals,
|
||||
sigset_t *const set,
|
||||
size_t arg_num,
|
||||
bool allow_empty_signal_array
|
||||
) {
|
||||
if (!allow_empty_signal_array && zend_hash_num_elements(user_signals) == 0) {
|
||||
zend_argument_value_error(arg_num, "cannot be empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (sigemptyset(set) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
zval *user_signal_no;
|
||||
ZEND_HASH_FOREACH_VAL(user_signals, user_signal_no) {
|
||||
bool failed = true;
|
||||
zend_long tmp = zval_try_get_long(user_signal_no, &failed);
|
||||
|
||||
if (failed) {
|
||||
zend_argument_type_error(arg_num, "signals must be of type int, %s given", zend_zval_value_name(user_signal_no));
|
||||
return false;
|
||||
}
|
||||
/* Signals are positive integers */
|
||||
if (tmp < 1 || tmp >= PCNTL_G(num_signals)) {
|
||||
/* PCNTL_G(num_signals) stores +1 from the last valid signal */
|
||||
zend_argument_value_error(arg_num, "signals must be between 1 and %d", PCNTL_G(num_signals)-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
int signal_no = (int) tmp;
|
||||
errno = 0;
|
||||
if (sigaddset(set, signal_no) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
/* {{{ Examine and change blocked signals */
|
||||
PHP_FUNCTION(pcntl_sigprocmask)
|
||||
{
|
||||
zend_long how, signo;
|
||||
zval *user_set, *user_oldset = NULL, *user_signo;
|
||||
sigset_t set, oldset;
|
||||
zend_long how;
|
||||
HashTable *user_set;
|
||||
/* Optional by-ref out-param array of old signals */
|
||||
zval *user_old_set = NULL;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3)
|
||||
Z_PARAM_LONG(how)
|
||||
Z_PARAM_ARRAY(user_set)
|
||||
Z_PARAM_ARRAY_HT(user_set)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(user_oldset)
|
||||
Z_PARAM_ZVAL(user_old_set)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (sigemptyset(&set) != 0 || sigemptyset(&oldset) != 0) {
|
||||
if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) {
|
||||
zend_argument_value_error(1, "must be one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
sigset_t old_set;
|
||||
if (sigemptyset(&old_set) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
|
||||
signo = zval_get_long(user_signo);
|
||||
if (sigaddset(&set, signo) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
sigset_t set;
|
||||
bool status = php_pcntl_set_user_signal_infos(user_set, &set, 2, /* allow_empty_signal_array */ how == SIG_SETMASK);
|
||||
/* Some error occurred */
|
||||
if (!status) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (sigprocmask(how, &set, &oldset) != 0) {
|
||||
if (sigprocmask(how, &set, &old_set) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (user_oldset != NULL) {
|
||||
user_oldset = zend_try_array_init(user_oldset);
|
||||
if (!user_oldset) {
|
||||
if (user_old_set != NULL) {
|
||||
user_old_set = zend_try_array_init(user_old_set);
|
||||
if (!user_old_set) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
for (signo = 1; signo < PCNTL_G(num_signals); ++signo) {
|
||||
if (sigismember(&oldset, signo) != 1) {
|
||||
for (int signal_no = 1; signal_no < PCNTL_G(num_signals); ++signal_no) {
|
||||
if (sigismember(&old_set, signal_no) != 1) {
|
||||
continue;
|
||||
}
|
||||
add_next_index_long(user_oldset, signo);
|
||||
add_next_index_long(user_old_set, signal_no);
|
||||
}
|
||||
}
|
||||
|
||||
@ -761,82 +815,109 @@ PHP_FUNCTION(pcntl_sigprocmask)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRUCT_SIGINFO_T
|
||||
# if defined(HAVE_SIGWAITINFO) && defined(HAVE_SIGTIMEDWAIT)
|
||||
static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */
|
||||
{
|
||||
zval *user_set, *user_signo, *user_siginfo = NULL;
|
||||
zend_long tv_sec = 0, tv_nsec = 0;
|
||||
sigset_t set;
|
||||
int signo;
|
||||
siginfo_t siginfo;
|
||||
struct timespec timeout;
|
||||
# ifdef HAVE_SIGWAITINFO
|
||||
|
||||
if (timedwait) {
|
||||
ZEND_PARSE_PARAMETERS_START(1, 4)
|
||||
Z_PARAM_ARRAY(user_set)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(user_siginfo)
|
||||
Z_PARAM_LONG(tv_sec)
|
||||
Z_PARAM_LONG(tv_nsec)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
} else {
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
Z_PARAM_ARRAY(user_set)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(user_siginfo)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
/* {{{ Synchronously wait for queued signals */
|
||||
PHP_FUNCTION(pcntl_sigwaitinfo)
|
||||
{
|
||||
HashTable *user_set;
|
||||
/* Optional by-ref array of ints */
|
||||
zval *user_siginfo = NULL;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 2)
|
||||
Z_PARAM_ARRAY_HT(user_set)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(user_siginfo)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
sigset_t set;
|
||||
bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false);
|
||||
/* Some error occurred */
|
||||
if (!status) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (sigemptyset(&set) != 0) {
|
||||
errno = 0;
|
||||
siginfo_t siginfo;
|
||||
int signal_no = sigwaitinfo(&set, &siginfo);
|
||||
/* sigwaitinfo() never sets errno to EAGAIN according to POSIX */
|
||||
if (signal_no == -1) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(user_set), user_signo) {
|
||||
signo = zval_get_long(user_signo);
|
||||
if (sigaddset(&set, signo) != 0) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (timedwait) {
|
||||
timeout.tv_sec = (time_t) tv_sec;
|
||||
timeout.tv_nsec = tv_nsec;
|
||||
signo = sigtimedwait(&set, &siginfo, &timeout);
|
||||
} else {
|
||||
signo = sigwaitinfo(&set, &siginfo);
|
||||
}
|
||||
if (signo == -1 && errno != EAGAIN) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
/* sigwaitinfo can return 0 on success on some platforms, e.g. NetBSD */
|
||||
if (!signal_no && siginfo.si_signo) {
|
||||
signal_no = siginfo.si_signo;
|
||||
}
|
||||
|
||||
/*
|
||||
* sigtimedwait and sigwaitinfo can return 0 on success on some
|
||||
* platforms, e.g. NetBSD
|
||||
*/
|
||||
if (!signo && siginfo.si_signo) {
|
||||
signo = siginfo.si_signo;
|
||||
}
|
||||
pcntl_siginfo_to_zval(signo, &siginfo, user_siginfo);
|
||||
RETURN_LONG(signo);
|
||||
pcntl_siginfo_to_zval(signal_no, &siginfo, user_siginfo);
|
||||
|
||||
RETURN_LONG(signal_no);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Synchronously wait for queued signals */
|
||||
PHP_FUNCTION(pcntl_sigwaitinfo)
|
||||
{
|
||||
pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
# endif
|
||||
# ifdef HAVE_SIGTIMEDWAIT
|
||||
/* {{{ Wait for queued signals */
|
||||
PHP_FUNCTION(pcntl_sigtimedwait)
|
||||
{
|
||||
pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||
HashTable *user_set;
|
||||
/* Optional by-ref array of ints */
|
||||
zval *user_siginfo = NULL;
|
||||
zend_long tv_sec = 0;
|
||||
zend_long tv_nsec = 0;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 4)
|
||||
Z_PARAM_ARRAY_HT(user_set)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_ZVAL(user_siginfo)
|
||||
Z_PARAM_LONG(tv_sec)
|
||||
Z_PARAM_LONG(tv_nsec)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
sigset_t set;
|
||||
bool status = php_pcntl_set_user_signal_infos(user_set, &set, 1, /* allow_empty_signal_array */ false);
|
||||
/* Some error occurred */
|
||||
if (!status) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (tv_sec < 0) {
|
||||
zend_argument_value_error(3, "must be greater than or equal to 0");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
/* Nanosecond between 0 and 1e9 */
|
||||
if (tv_nsec < 0 || tv_nsec >= 1000000000) {
|
||||
zend_argument_value_error(4, "must be between 0 and 1e9");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
if (UNEXPECTED(tv_sec == 0 && tv_nsec == 0)) {
|
||||
zend_value_error("pcntl_sigtimedwait(): At least one of argument #3 ($seconds) or argument #4 ($nanoseconds) must be greater than 0");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
siginfo_t siginfo;
|
||||
struct timespec timeout;
|
||||
timeout.tv_sec = (time_t) tv_sec;
|
||||
timeout.tv_nsec = tv_nsec;
|
||||
int signal_no = sigtimedwait(&set, &siginfo, &timeout);
|
||||
if (signal_no == -1) {
|
||||
if (errno != EAGAIN) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* sigtimedwait can return 0 on success on some platforms, e.g. NetBSD */
|
||||
if (!signal_no && siginfo.si_signo) {
|
||||
signal_no = siginfo.si_signo;
|
||||
}
|
||||
|
||||
pcntl_siginfo_to_zval(signal_no, &siginfo, user_siginfo);
|
||||
|
||||
RETURN_LONG(signal_no);
|
||||
}
|
||||
/* }}} */
|
||||
# endif
|
||||
|
@ -5,9 +5,12 @@ pcntl
|
||||
posix
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!function_exists('pcntl_sigwaitinfo') or !function_exists('pcntl_sigtimedwait')) die('skip required functionality is not available');
|
||||
if (
|
||||
!function_exists('pcntl_sigprocmask')
|
||||
or !function_exists('pcntl_sigwaitinfo')
|
||||
or !function_exists('pcntl_sigtimedwait')
|
||||
) { die('skip required functionality is not available'); }
|
||||
elseif (!defined('CLD_EXITED')) die('skip CLD_EXITED not defined');
|
||||
elseif (getenv('SKIP_ASAN')) die('skip Fails intermittently under asan/msan');
|
||||
elseif (getenv("SKIP_REPEAT")) die("skip cannot be repeated");
|
||||
elseif (str_contains(PHP_OS, 'FreeBSD')) die('skip Results in parallel test runner hang on FreeBSD');
|
||||
?>
|
||||
@ -20,7 +23,7 @@ if ($pid == -1) {
|
||||
} else if ($pid) {
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD,(string)SIGTERM));
|
||||
$oldset = array();
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(), $oldset);
|
||||
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGINT), $oldset);
|
||||
var_dump(in_array(SIGCHLD, $oldset));
|
||||
var_dump(in_array(SIGTERM, $oldset));
|
||||
|
||||
@ -49,27 +52,6 @@ if ($pid == -1) {
|
||||
echo "signo === pid\n";
|
||||
var_dump($siginfo['pid'] === $pid);
|
||||
pcntl_waitpid($pid, $status);
|
||||
|
||||
set_error_handler(function($errno, $errstr) { echo "Error triggered\n"; }, E_WARNING);
|
||||
|
||||
echo "sigprocmask with invalid arguments\n";
|
||||
|
||||
/* Valgrind expectedly complains about this:
|
||||
* "sigprocmask: unknown 'how' field 2147483647"
|
||||
* Skip */
|
||||
if (getenv("USE_ZEND_ALLOC") !== '0') {
|
||||
var_dump(pcntl_sigprocmask(PHP_INT_MAX, array(SIGTERM)));
|
||||
} else {
|
||||
echo "Error triggered\n";
|
||||
echo "bool(false)\n";
|
||||
}
|
||||
var_dump(pcntl_sigprocmask(SIG_SETMASK, array(0)));
|
||||
|
||||
echo "sigwaitinfo with invalid arguments\n";
|
||||
var_dump(pcntl_sigwaitinfo(array(0)));
|
||||
|
||||
echo "sigtimedwait with invalid arguments\n";
|
||||
var_dump(pcntl_sigtimedwait(array(SIGTERM), $signo, PHP_INT_MAX, PHP_INT_MAX));
|
||||
} else {
|
||||
$siginfo = NULL;
|
||||
pcntl_sigtimedwait(array(SIGINT), $siginfo, 3600, 0);
|
||||
@ -94,14 +76,3 @@ signo === uid
|
||||
bool(true)
|
||||
signo === pid
|
||||
bool(true)
|
||||
sigprocmask with invalid arguments
|
||||
Error triggered
|
||||
bool(false)
|
||||
Error triggered
|
||||
bool(false)
|
||||
sigwaitinfo with invalid arguments
|
||||
Error triggered
|
||||
bool(false)
|
||||
sigtimedwait with invalid arguments
|
||||
Error triggered
|
||||
int(-1)
|
||||
|
@ -5,34 +5,66 @@ pcntl
|
||||
posix
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!function_exists('pcntl_sigwaitinfo') or !function_exists('pcntl_sigtimedwait')) die('skip required functionality is not available');
|
||||
if (!function_exists("pcntl_sigprocmask")) die("skip pcntl_sigprocmask() not available");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// Clear mask
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(), $prev);
|
||||
const SIGNO_NAMES = [
|
||||
SIGINT => "SIGINT",
|
||||
SIGTERM => "SIGTERM",
|
||||
SIGCHLD => "SIGCHLD",
|
||||
];
|
||||
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD,SIGTERM), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_BLOCK, array(SIGINT), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGINT), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(SIGINT), $old);
|
||||
var_dump(count($old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, array(), $old);
|
||||
var_dump(count($old));
|
||||
function map_signo_to_name(int $no): string {
|
||||
return SIGNO_NAMES[$no];
|
||||
}
|
||||
|
||||
// Clear mask
|
||||
pcntl_sigprocmask(SIG_SETMASK, [], $prev);
|
||||
|
||||
pcntl_sigprocmask(SIG_BLOCK, [SIGCHLD, SIGTERM], $old);
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
pcntl_sigprocmask(SIG_BLOCK, [SIGINT], $old);
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
pcntl_sigprocmask(SIG_UNBLOCK, [SIGINT], $old);
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, [SIGINT], $old);
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
pcntl_sigprocmask(SIG_SETMASK, [], $old);
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
|
||||
// Restore previous mask
|
||||
pcntl_sigprocmask(SIG_SETMASK, $prev, $old);
|
||||
var_dump(count($old));
|
||||
var_dump(array_map(map_signo_to_name(...), $old));
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
int(2)
|
||||
int(3)
|
||||
int(2)
|
||||
int(1)
|
||||
int(0)
|
||||
array(0) {
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(7) "SIGTERM"
|
||||
[1]=>
|
||||
string(7) "SIGCHLD"
|
||||
}
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(6) "SIGINT"
|
||||
[1]=>
|
||||
string(7) "SIGTERM"
|
||||
[2]=>
|
||||
string(7) "SIGCHLD"
|
||||
}
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(7) "SIGTERM"
|
||||
[1]=>
|
||||
string(7) "SIGCHLD"
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(6) "SIGINT"
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ pcntl_alarm(0);
|
||||
var_dump(pcntl_alarm(60));
|
||||
var_dump(pcntl_alarm(1) > 0);
|
||||
$siginfo = array();
|
||||
var_dump(pcntl_sigtimedwait(array(SIGALRM),$siginfo,2) === SIGALRM);
|
||||
$signo = pcntl_sigtimedwait(array(SIGALRM),$siginfo,2);
|
||||
var_dump($signo === SIGALRM);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
|
67
ext/pcntl/tests/pcntl_sigprocmask_errors.phpt
Normal file
67
ext/pcntl/tests/pcntl_sigprocmask_errors.phpt
Normal file
@ -0,0 +1,67 @@
|
||||
--TEST--
|
||||
pcntl_sigprocmask() errors
|
||||
--EXTENSIONS--
|
||||
pcntl
|
||||
--SKIPIF--
|
||||
<?php if (!function_exists("pcntl_sigprocmask")) die("skip pcntl_sigprocmask() not available"); ?>
|
||||
--INI--
|
||||
max_execution_time=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* Invalid mode */
|
||||
try {
|
||||
$signals = [SIGTERM];
|
||||
$signal_no = pcntl_sigprocmask(-1, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
/* This used to return -1 prior to PHP 8.4.0 */
|
||||
$signals = [];
|
||||
$signal_no = pcntl_sigprocmask(SIG_BLOCK, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
try {
|
||||
$signals = [0];
|
||||
$signal_no = pcntl_sigprocmask(SIG_BLOCK, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signals = [-1];
|
||||
$signal_no = pcntl_sigprocmask(SIG_BLOCK, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
try {
|
||||
$signals = ["not a signal"];
|
||||
$signal_no = pcntl_sigprocmask(SIG_BLOCK, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
/* Unlikely valid signal */
|
||||
try {
|
||||
$signals = [2**10];
|
||||
$signal_no = pcntl_sigprocmask(SIG_BLOCK, $signals);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
ValueError: pcntl_sigprocmask(): Argument #1 ($mode) must be one of SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK
|
||||
ValueError: pcntl_sigprocmask(): Argument #2 ($signals) cannot be empty
|
||||
ValueError: pcntl_sigprocmask(): Argument #2 ($signals) signals must be between 1 and %d
|
||||
ValueError: pcntl_sigprocmask(): Argument #2 ($signals) signals must be between 1 and %d
|
||||
TypeError: pcntl_sigprocmask(): Argument #2 ($signals) signals must be of type int, string given
|
||||
ValueError: pcntl_sigprocmask(): Argument #2 ($signals) signals must be between 1 and %d
|
98
ext/pcntl/tests/pcntl_sigtimedwait_errors.phpt
Normal file
98
ext/pcntl/tests/pcntl_sigtimedwait_errors.phpt
Normal file
@ -0,0 +1,98 @@
|
||||
--TEST--
|
||||
pcntl_sigtimedwait() errors
|
||||
--EXTENSIONS--
|
||||
pcntl
|
||||
--SKIPIF--
|
||||
<?php if (!function_exists("pcntl_sigtimedwait")) die("skip pcntl_sigtimedwait() not available"); ?>
|
||||
--INI--
|
||||
max_execution_time=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
/* This used to return -1 prior to PHP 8.4.0 */
|
||||
$signals = [];
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
/* Invalid signal numbers */
|
||||
try {
|
||||
$signals = [0];
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signals = [-1];
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signals = [2**10];
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
/* Invalid signal type */
|
||||
try {
|
||||
$signals = ["not a signal"];
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
/* Invalid (nano)second values */
|
||||
$signals = [SIGTERM];
|
||||
try {
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, -1);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 1, -1);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 1, PHP_INT_MAX);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signal_no = var_dump(pcntl_sigtimedwait([SIGTERM], $signal_infos, 0, 0));
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
/* 1_000_000_000ns = 1s so must throw */
|
||||
try {
|
||||
$signal_no = var_dump(pcntl_sigtimedwait([SIGTERM], $signal_infos, 0, 1_000_000_000));
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) cannot be empty
|
||||
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
|
||||
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
|
||||
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
|
||||
TypeError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be of type int, string given
|
||||
ValueError: pcntl_sigtimedwait(): Argument #3 ($seconds) must be greater than or equal to 0
|
||||
ValueError: pcntl_sigtimedwait(): Argument #4 ($nanoseconds) must be between 0 and 1e9
|
||||
ValueError: pcntl_sigtimedwait(): Argument #4 ($nanoseconds) must be between 0 and 1e9
|
||||
ValueError: pcntl_sigtimedwait(): At least one of argument #3 ($seconds) or argument #4 ($nanoseconds) must be greater than 0
|
||||
ValueError: pcntl_sigtimedwait(): Argument #4 ($nanoseconds) must be between 0 and 1e9
|
58
ext/pcntl/tests/pcntl_sigwaitinfo_errors.phpt
Normal file
58
ext/pcntl/tests/pcntl_sigwaitinfo_errors.phpt
Normal file
@ -0,0 +1,58 @@
|
||||
--TEST--
|
||||
pcntl_sigwaitinfo() errors
|
||||
--EXTENSIONS--
|
||||
pcntl
|
||||
--SKIPIF--
|
||||
<?php if (!function_exists("pcntl_sigwaitinfo")) die("skip pcntl_sigtimedwait() not available"); ?>
|
||||
--INI--
|
||||
max_execution_time=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
/* This used to return -1 prior to PHP 8.4.0 */
|
||||
$signals = [];
|
||||
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
try {
|
||||
$signals = [0];
|
||||
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
try {
|
||||
$signals = [-1];
|
||||
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
try {
|
||||
$signals = ["not a signal"];
|
||||
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
|
||||
/* Unlikely valid signal */
|
||||
try {
|
||||
$signals = [2**10];
|
||||
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
|
||||
var_dump($signal_no);
|
||||
} catch (\Throwable $e) {
|
||||
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
ValueError: pcntl_sigwaitinfo(): Argument #1 ($signals) cannot be empty
|
||||
ValueError: pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be between 1 and %d
|
||||
ValueError: pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be between 1 and %d
|
||||
TypeError: pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be of type int, string given
|
||||
ValueError: pcntl_sigwaitinfo(): Argument #1 ($signals) signals must be between 1 and %d
|
Loading…
Reference in New Issue
Block a user