Skip to content

Commit 59d5b3d

Browse files
authored
Accept null for microseconds argument in stream_select() (php#6879)
The deprecation of passing null is thrown otherwise. If the timeout is calculated conditionally before calling stream_select(), passing to avoid the deprecation seems unreasonable, example: https://github.com/amphp/amp/blob/7d4bbc6e0b47c6bb39b6cce1a4b5942e0c5125fb/lib/Loop/NativeDriver.php#L286 Also enforce that if $seconds is null, then $microseconds should be null as well. However 0 is still accepted (with deprecation) for backwards compatibility.
1 parent 7645265 commit 59d5b3d

7 files changed

+53
-7
lines changed

ext/standard/basic_functions.stub.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ function soundex(string $string): string {}
12091209

12101210
/* streamsfuncs.c */
12111211

1212-
function stream_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, int $microseconds = 0): int|false {}
1212+
function stream_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, ?int $microseconds = null): int|false {}
12131213

12141214
/** @return resource */
12151215
function stream_context_create(?array $options = null, ?array $params = null) {}

ext/standard/basic_functions_arginfo.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 2d92e992837a61a052eea6d0257837aaccc54be6 */
2+
* Stub hash: 55f11c2d6cc7ba342b1062104f3838866ad9135d */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
55
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
@@ -1847,7 +1847,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_stream_select, 0, 4, MAY_BE_LONG
18471847
ZEND_ARG_TYPE_INFO(1, write, IS_ARRAY, 1)
18481848
ZEND_ARG_TYPE_INFO(1, except, IS_ARRAY, 1)
18491849
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 1)
1850-
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, microseconds, IS_LONG, 0, "0")
1850+
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, microseconds, IS_LONG, 1, "null")
18511851
ZEND_END_ARG_INFO()
18521852

18531853
ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_context_create, 0, 0, 0)

ext/standard/streamsfuncs.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ PHP_FUNCTION(stream_select)
745745
int retval, sets = 0;
746746
zend_long sec, usec = 0;
747747
bool secnull;
748+
bool usecnull = 1;
748749
int set_count, max_set_count = 0;
749750

750751
ZEND_PARSE_PARAMETERS_START(4, 5)
@@ -753,7 +754,7 @@ PHP_FUNCTION(stream_select)
753754
Z_PARAM_ARRAY_EX2(e_array, 1, 1, 0)
754755
Z_PARAM_LONG_OR_NULL(sec, secnull)
755756
Z_PARAM_OPTIONAL
756-
Z_PARAM_LONG(usec)
757+
Z_PARAM_LONG_OR_NULL(usec, usecnull)
757758
ZEND_PARSE_PARAMETERS_END();
758759

759760
FD_ZERO(&rfds);
@@ -788,6 +789,15 @@ PHP_FUNCTION(stream_select)
788789

789790
PHP_SAFE_MAX_FD(max_fd, max_set_count);
790791

792+
if (secnull && !usecnull) {
793+
if (usec == 0) {
794+
php_error_docref(NULL, E_DEPRECATED, "Argument #5 ($microseconds) should be null instead of 0 when argument #4 ($seconds) is null");
795+
} else {
796+
zend_argument_value_error(5, "must be null when argument #4 ($seconds) is null");
797+
RETURN_THROWS();
798+
}
799+
}
800+
791801
/* If seconds is not set to null, build the timeval, else we wait indefinitely */
792802
if (!secnull) {
793803
if (sec < 0) {

ext/standard/tests/general_functions/proc_open_sockets1.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ while ($pipes) {
2525
$w = null;
2626
$e = null;
2727

28-
if (!stream_select($r, $w, $e, null, 0)) {
28+
if (!stream_select($r, $w, $e, null)) {
2929
throw new Error("Select failed");
3030
}
3131

ext/standard/tests/general_functions/proc_open_sockets2.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function poll($pipe, $read = true)
99
$w = ($read == false) ? [$pipe] : null;
1010
$e = null;
1111

12-
if (!stream_select($r, $w, $e, null, 0)) {
12+
if (!stream_select($r, $w, $e, null)) {
1313
throw new \Error("Select failed");
1414
}
1515
}

ext/standard/tests/general_functions/proc_open_sockets3.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function poll($pipe, $read = true)
99
$w = ($read == false) ? [$pipe] : null;
1010
$e = null;
1111

12-
if (!stream_select($r, $w, $e, null, 0)) {
12+
if (!stream_select($r, $w, $e, null)) {
1313
throw new \Error("Select failed");
1414
}
1515
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
stream_select allows null for microsecond timeout if timeout is null
3+
--FILE--
4+
<?php
5+
6+
$read = [fopen(__FILE__, 'r')];
7+
$write = null;
8+
$except = null;
9+
10+
error_reporting(-1);
11+
set_error_handler(function ($errno, $errstr) {
12+
print $errno . " " . $errstr . "\n";
13+
});
14+
15+
stream_select($read, $write, $except, null, null);
16+
var_dump($read);
17+
18+
print "\n";
19+
20+
stream_select($read, $write, $except, null, 0);
21+
22+
stream_select($read, $write, $except, null, 1);
23+
?>
24+
--EXPECTF--
25+
array(1) {
26+
[0]=>
27+
resource(%d) of type (stream)
28+
}
29+
30+
8192 stream_select(): Argument #5 ($microseconds) should be null instead of 0 when argument #4 ($seconds) is null
31+
32+
Fatal error: Uncaught ValueError: stream_select(): Argument #5 ($microseconds) must be null when argument #4 ($seconds) is null in %s
33+
Stack trace:
34+
#0 %s stream_select(Array, NULL, NULL, NULL, 1)
35+
#1 {main}
36+
%s

0 commit comments

Comments
 (0)