Skip to content

Commit 5902b35

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #79000
2 parents 3958592 + 10eb0b3 commit 5902b35

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Bug #79000: Non-blocking socket stream reports EAGAIN as error
3+
--SKIPIF--
4+
<?php
5+
if (PHP_OS_FAMILY == 'Windows') die('skip Not for Windows');
6+
?>
7+
--FILE--
8+
<?php
9+
10+
[$sock1, $sock2] = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
11+
$str = str_repeat('a', 1000000);
12+
stream_set_blocking($sock1, false);
13+
var_dump(fwrite($sock1, $str));
14+
var_dump(fwrite($sock1, $str));
15+
16+
?>
17+
--EXPECTF--
18+
int(%d)
19+
int(%d)

main/streams/xp_socket.c

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,30 +73,36 @@ static ssize_t php_sockop_write(php_stream *stream, const char *buf, size_t coun
7373
didwrite = send(sock->socket, buf, XP_SOCK_BUF_SIZE(count), (sock->is_blocked && ptimeout) ? MSG_DONTWAIT : 0);
7474

7575
if (didwrite <= 0) {
76-
int err = php_socket_errno();
7776
char *estr;
77+
int err = php_socket_errno();
78+
if (err == EWOULDBLOCK || err == EAGAIN) {
79+
if (sock->is_blocked) {
80+
int retval;
7881

79-
if (sock->is_blocked && (err == EWOULDBLOCK || err == EAGAIN)) {
80-
int retval;
81-
82-
sock->timeout_event = 0;
82+
sock->timeout_event = 0;
8383

84-
do {
85-
retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout);
84+
do {
85+
retval = php_pollfd_for(sock->socket, POLLOUT, ptimeout);
8686

87-
if (retval == 0) {
88-
sock->timeout_event = 1;
89-
break;
90-
}
87+
if (retval == 0) {
88+
sock->timeout_event = 1;
89+
break;
90+
}
9191

92-
if (retval > 0) {
93-
/* writable now; retry */
94-
goto retry;
95-
}
92+
if (retval > 0) {
93+
/* writable now; retry */
94+
goto retry;
95+
}
9696

97-
err = php_socket_errno();
98-
} while (err == EINTR);
97+
err = php_socket_errno();
98+
} while (err == EINTR);
99+
} else {
100+
/* EWOULDBLOCK/EAGAIN is not an error for a non-blocking stream.
101+
* Report zero byte write instead. */
102+
return 0;
103+
}
99104
}
105+
100106
estr = php_socket_strerror(err, NULL, 0);
101107
php_error_docref(NULL, E_NOTICE, "send of " ZEND_LONG_FMT " bytes failed with errno=%d %s",
102108
(zend_long)count, err, estr);

0 commit comments

Comments
 (0)