Skip to content

Commit 38f6734

Browse files
committed
More fixes
1 parent e2a8dba commit 38f6734

File tree

5 files changed

+77
-21
lines changed

5 files changed

+77
-21
lines changed

UPGRADING

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ PHP 8.3 UPGRADE NOTES
5959
modifiable pointers but was rejected due to complexity. For this reason, it
6060
was decided to remove the feature instead.
6161

62+
- PCNTL:
63+
. The functions pcntl_sigwaitinfo() and pcntl_sigtimedwait() now throw:
64+
- A TypeError if a value of the $signals array is not an integer
65+
- A ValueError if the $signals array is empty
66+
- A ValueError if a value of the $signals array is not a valid signal number
67+
Moreover, those functions now always return false on failure.
68+
In some case previously it could return the value -1.
69+
. The function pcntl_sigtimedwait() will also now throw:
70+
- A ValueError if $seconds is less than 0
71+
- A ValueError if $nanoseconds is less than 0 or greater than 1e9
72+
- A ValueError if both $seconds and $nanoseconds are 0
73+
6274
- Standard:
6375
. The range() function has had various changes:
6476
* A TypeError is now thrown when passing objects, resources, or arrays

ext/pcntl/pcntl.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,8 @@ static bool php_pcntl_process_user_signal_infos(
795795
}
796796
/* Signals are positive integers */
797797
if (tmp < 1 || tmp >= PCNTL_G(num_signals)) {
798-
zend_argument_value_error(1, "signals must be between 1 and %d", PCNTL_G(num_signals));
798+
/* PCNTL_G(num_signals) stores +1 from the last valid signal */
799+
zend_argument_value_error(1, "signals must be between 1 and %d", PCNTL_G(num_signals)-1);
799800
return false;
800801
}
801802

@@ -833,7 +834,8 @@ PHP_FUNCTION(pcntl_sigwaitinfo)
833834
errno = 0;
834835
siginfo_t siginfo;
835836
int signal_no = sigwaitinfo(&set, &siginfo);
836-
if (signal_no == -1 && errno != EAGAIN) {
837+
/* sigwaitinfo() never sets errno to EAGAIN according to POSIX */
838+
if (signal_no == -1) {
837839
PCNTL_G(last_error) = errno;
838840
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
839841
RETURN_FALSE;
@@ -858,7 +860,6 @@ PHP_FUNCTION(pcntl_sigtimedwait)
858860
zval *user_siginfo = NULL;
859861
zend_long tv_sec = 0;
860862
zend_long tv_nsec = 0;
861-
struct timespec timeout;
862863

863864
ZEND_PARSE_PARAMETERS_START(1, 4)
864865
Z_PARAM_ARRAY_HT(user_set)
@@ -874,17 +875,31 @@ PHP_FUNCTION(pcntl_sigtimedwait)
874875
if (!status) {
875876
RETURN_FALSE;
876877
}
878+
if (tv_sec < 0) {
879+
zend_argument_value_error(3, "must be greater than or equal to 0");
880+
RETURN_THROWS();
881+
}
882+
/* Nanosecond between 0 and 1e9 */
883+
if (tv_nsec < 0 || tv_nsec > 1000000000) {
884+
zend_argument_value_error(4, "must be between 0 and 1e9");
885+
RETURN_THROWS();
886+
}
887+
if (UNEXPECTED(tv_sec == 0 && tv_nsec == 0)) {
888+
zend_value_error("pcntl_sigtimedwait(): At least one of argument #3 ($seconds) or argument #4 ($nanoseconds) must be greater than 0");
889+
RETURN_THROWS();
890+
}
877891

878892
errno = 0;
879893
siginfo_t siginfo;
894+
struct timespec timeout;
880895
timeout.tv_sec = (time_t) tv_sec;
881896
timeout.tv_nsec = tv_nsec;
882897
int signal_no = sigtimedwait(&set, &siginfo, &timeout);
898+
// TODO Drop check for EAGAIN as it will return -1?
883899
if (signal_no == -1 && errno != EAGAIN) {
884900
PCNTL_G(last_error) = errno;
885901
php_error_docref(NULL, E_WARNING, "%s", strerror(errno));
886-
// TODO BC Break, as -1 used to be returned?
887-
// RETURN_FALSE;
902+
RETURN_FALSE;
888903
}
889904

890905
/* sigtimedwait can return 0 on success on some platforms, e.g. NetBSD */

ext/pcntl/tests/002.phpt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@ if ($pid == -1) {
6464
echo "bool(false)\n";
6565
}
6666
var_dump(pcntl_sigprocmask(SIG_SETMASK, array(0)));
67-
68-
echo "sigwaitinfo with invalid arguments\n";
69-
var_dump(pcntl_sigwaitinfo(array(0)));
70-
71-
echo "sigtimedwait with invalid arguments\n";
72-
var_dump(pcntl_sigtimedwait(array(SIGTERM), $signo, PHP_INT_MAX, PHP_INT_MAX));
7367
} else {
7468
$siginfo = NULL;
7569
pcntl_sigtimedwait(array(SIGINT), $siginfo, 3600, 0);
@@ -99,9 +93,3 @@ Error triggered
9993
bool(false)
10094
Error triggered
10195
bool(false)
102-
sigwaitinfo with invalid arguments
103-
Error triggered
104-
bool(false)
105-
sigtimedwait with invalid arguments
106-
Error triggered
107-
int(-1)

ext/pcntl/tests/pcntl_sigtimedwait_errors.phpt

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,66 @@ try {
1313
/* This used to return -1 prior to PHP 8.3.0 */
1414
$signals = [];
1515
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
16+
var_dump($signal_no);
1617
} catch (\Throwable $e) {
1718
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1819
}
1920

21+
/* Invalid signal numbers */
2022
try {
2123
$signals = [0];
2224
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
25+
var_dump($signal_no);
2326
} catch (\Throwable $e) {
2427
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
2528
}
2629
try {
2730
$signals = [-1];
2831
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
32+
var_dump($signal_no);
33+
} catch (\Throwable $e) {
34+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
35+
}
36+
try {
37+
$signals = [2**10];
38+
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
39+
var_dump($signal_no);
2940
} catch (\Throwable $e) {
3041
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
3142
}
3243

44+
/* Invalid signal type */
3345
try {
3446
$signals = ["not a signal"];
3547
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
48+
var_dump($signal_no);
3649
} catch (\Throwable $e) {
3750
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
3851
}
3952

40-
/* Unlikely valid signal */
53+
/* Invalid (nano)second values */
54+
$signals = [SIGTERM];
4155
try {
42-
$signals = [2**10];
43-
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 2);
56+
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, -1);
57+
var_dump($signal_no);
58+
} catch (\Throwable $e) {
59+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
60+
}
61+
try {
62+
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 1, -1);
63+
var_dump($signal_no);
64+
} catch (\Throwable $e) {
65+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
66+
}
67+
try {
68+
$signal_no = pcntl_sigtimedwait($signals, $signal_infos, 1, PHP_INT_MAX);
69+
var_dump($signal_no);
70+
} catch (\Throwable $e) {
71+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
72+
}
73+
try {
74+
$signal_no = var_dump(pcntl_sigtimedwait([SIGTERM], $signal_infos, 0, 0));
75+
var_dump($signal_no);
4476
} catch (\Throwable $e) {
4577
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
4678
}
@@ -49,5 +81,9 @@ try {
4981
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) cannot be empty
5082
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
5183
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
52-
TypeError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be of type int, string given
5384
ValueError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be between 1 and %d
85+
TypeError: pcntl_sigtimedwait(): Argument #1 ($signals) signals must be of type int, string given
86+
ValueError: pcntl_sigtimedwait(): Argument #3 ($seconds) must be greater than or equal to 0
87+
ValueError: pcntl_sigtimedwait(): Argument #4 ($nanoseconds) must be between 0 and 1e9
88+
ValueError: pcntl_sigtimedwait(): Argument #4 ($nanoseconds) must be between 0 and 1e9
89+
ValueError: pcntl_sigtimedwait(): At least one of argument #3 ($seconds) or argument #4 ($nanoseconds) must be greater than 0

ext/pcntl/tests/pcntl_sigwaitinfo_errors.phpt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,30 @@ try {
1313
/* This used to return -1 prior to PHP 8.3.0 */
1414
$signals = [];
1515
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
16+
var_dump($signal_no);
1617
} catch (\Throwable $e) {
1718
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
1819
}
1920

2021
try {
2122
$signals = [0];
2223
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
24+
var_dump($signal_no);
2325
} catch (\Throwable $e) {
2426
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
2527
}
2628
try {
2729
$signals = [-1];
2830
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
31+
var_dump($signal_no);
2932
} catch (\Throwable $e) {
3033
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
3134
}
3235

3336
try {
3437
$signals = ["not a signal"];
3538
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
39+
var_dump($signal_no);
3640
} catch (\Throwable $e) {
3741
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
3842
}
@@ -41,6 +45,7 @@ try {
4145
try {
4246
$signals = [2**10];
4347
$signal_no = pcntl_sigwaitinfo($signals, $signal_infos);
48+
var_dump($signal_no);
4449
} catch (\Throwable $e) {
4550
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
4651
}

0 commit comments

Comments
 (0)