Skip to content

Commit e80073d

Browse files
committed
Fix GH-10406: feof() behavior change for UNIX based socket resources
This change restores the old behaviour for the server socket streams that don't support IO. This is now stored in the stream flags so it can be later used to do some other decisions and possibly introduce some better error reporting. Closes GH-10877
1 parent dc0171b commit e80073d

File tree

6 files changed

+45
-3
lines changed

6 files changed

+45
-3
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.6
44

5+
- Streams:
6+
. Fixed bug GH-10406 (feof() behavior change for UNIX based socket
7+
resources). (Jakub Zelenka)
58

69
30 Mar 2023, PHP 8.2.5
710

ext/openssl/xp_ssl.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,8 +2429,15 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
24292429

24302430
if (sslsock->s.socket == -1) {
24312431
alive = 0;
2432-
} else if ((!sslsock->ssl_active && value == 0 && ((MSG_DONTWAIT != 0) || !sslsock->s.is_blocked)) ||
2433-
php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
2432+
} else if (
2433+
(
2434+
!sslsock->ssl_active &&
2435+
value == 0 &&
2436+
!(stream->flags & PHP_STREAM_FLAG_NO_IO) &&
2437+
((MSG_DONTWAIT != 0) || !sslsock->s.is_blocked)
2438+
) ||
2439+
php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0
2440+
) {
24342441
/* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */
24352442
/* additionally, we don't use this optimization if SSL is active because in that case, we're not using MSG_DONTWAIT */
24362443
if (sslsock->ssl_active) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-10406: feof() behavior change for UNIX based socket resources
3+
--SKIPIF--
4+
<?php
5+
if (!strncasecmp(PHP_OS, 'WIN', 3)) die("skip. Do not run on Windows");
6+
?>
7+
--FILE--
8+
<?php
9+
$socket_path = '/tmp/gh-10406-test.socket';
10+
11+
if (file_exists($socket_path)) {
12+
unlink($socket_path);
13+
}
14+
15+
$socket = stream_socket_server('unix://' . $socket_path);
16+
var_dump(feof($socket));
17+
unlink($socket_path);
18+
?>
19+
--EXPECT--
20+
bool(false)

main/php_streams.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ struct _php_stream_wrapper {
188188
/* Do not close handle except it is explicitly closed by user (e.g. fclose) */
189189
#define PHP_STREAM_FLAG_NO_RSCR_DTOR_CLOSE 0x200
190190

191+
#define PHP_STREAM_FLAG_NO_IO 0x400
192+
191193
#define PHP_STREAM_FLAG_WAS_WRITTEN 0x80000000
192194

193195
struct _php_stream {

main/streams/transports.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
169169
failed = true;
170170
}
171171
}
172+
if (!failed) {
173+
stream->flags |= PHP_STREAM_FLAG_NO_IO;
174+
}
172175
}
173176
}
174177
} zend_catch {

main/streams/xp_socket.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,14 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
337337

338338
if (sock->socket == -1) {
339339
alive = 0;
340-
} else if ((value == 0 && ((MSG_DONTWAIT != 0) || !sock->is_blocked)) || php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
340+
} else if (
341+
(
342+
value == 0 &&
343+
!(stream->flags & PHP_STREAM_FLAG_NO_IO) &&
344+
((MSG_DONTWAIT != 0) || !sock->is_blocked)
345+
) ||
346+
php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0
347+
) {
341348
/* the poll() call was skipped if the socket is non-blocking (or MSG_DONTWAIT is available) and if the timeout is zero */
342349
#ifdef PHP_WIN32
343350
int ret;

0 commit comments

Comments
 (0)