Skip to content

Commit fa341e0

Browse files
matyhtfsy-records
andauthored
fix fread bugs (swoole#3972)
* fix fread bugs * Update nonblock.phpt Fix php72 error : Parse error: syntax error, unexpected ')' * fix tests Co-authored-by: 沈唁 <52o@qq52o.cn>
1 parent f7e0bc6 commit fa341e0

File tree

5 files changed

+80
-44
lines changed

5 files changed

+80
-44
lines changed

ext-src/swoole_runtime.cc

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ ZEND_END_ARG_INFO()
9292

9393
static zend_class_entry *swoole_runtime_ce;
9494

95-
static php_stream_ops socket_ops
96-
{
95+
static php_stream_ops socket_ops {
9796
socket_write,
9897
socket_read,
9998
socket_close,
@@ -105,20 +104,16 @@ static php_stream_ops socket_ops
105104
socket_set_option,
106105
};
107106

108-
struct php_swoole_netstream_data_t
109-
{
107+
struct php_swoole_netstream_data_t {
110108
php_netstream_data_t stream;
111109
Socket *socket;
112110
bool blocking;
113-
double read_timeout;
114-
double write_timeout;
115111
};
116112

117113
static bool runtime_hook_init = false;
118114
static int runtime_hook_flags = 0;
119115

120-
static struct
121-
{
116+
static struct {
122117
php_stream_transport_factory tcp;
123118
php_stream_transport_factory udp;
124119
php_stream_transport_factory _unix;
@@ -270,8 +265,7 @@ static inline char *parse_ip_address_ex(const char *str, size_t str_len, int *po
270265
return host;
271266
}
272267

273-
static php_stream_size_t socket_write(php_stream *stream, const char *buf, size_t count)
274-
{
268+
static php_stream_size_t socket_write(php_stream *stream, const char *buf, size_t count) {
275269
php_swoole_netstream_data_t *abstract;
276270
Socket *sock;
277271
ssize_t didwrite = -1;
@@ -286,7 +280,12 @@ static php_stream_size_t socket_write(php_stream *stream, const char *buf, size_
286280
goto _exit;
287281
}
288282

289-
didwrite = sock->send_all(buf, count);
283+
if (abstract->blocking) {
284+
didwrite = sock->send_all(buf, count);
285+
} else {
286+
didwrite = sock->get_socket()->send(buf, count, 0);
287+
sock->set_err(errno);
288+
}
290289

291290
if (didwrite < 0 || (size_t) didwrite != count) {
292291
/* we do not expect the outer layer to continue to call the send syscall in a loop
@@ -303,6 +302,16 @@ static php_stream_size_t socket_write(php_stream *stream, const char *buf, size_
303302
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), didwrite, 0);
304303
}
305304

305+
if (didwrite < 0) {
306+
if (sock->errCode == ETIMEDOUT || sock->get_socket()->catch_error(sock->errCode) == SW_WAIT) {
307+
didwrite = 0;
308+
} else {
309+
stream->eof = 1;
310+
}
311+
} else if (didwrite == 0) {
312+
stream->eof = 1;
313+
}
314+
306315
_exit:
307316
#if PHP_VERSION_ID < 70400
308317
if (didwrite < 0) {
@@ -328,17 +337,27 @@ static php_stream_size_t socket_read(php_stream *stream, char *buf, size_t count
328337
goto _exit;
329338
}
330339

331-
nr_bytes = sock->recv(buf, count);
340+
if (abstract->blocking) {
341+
nr_bytes = sock->recv(buf, count);
342+
} else {
343+
nr_bytes = sock->get_socket()->recv(buf, count, 0);
344+
sock->set_err(errno);
345+
}
332346

333-
/**
334-
* sock->errCode != ETIMEDOUT : Compatible with sync blocking IO
335-
*/
336-
stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && sock->errCode != ETIMEDOUT &&
337-
sock->get_socket()->catch_error(sock->errCode) == SW_CLOSE));
338347
if (nr_bytes > 0) {
339348
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
340349
}
341350

351+
if (nr_bytes < 0) {
352+
if (sock->errCode == ETIMEDOUT || sock->get_socket()->catch_error(sock->errCode) == SW_WAIT) {
353+
nr_bytes = 0;
354+
} else {
355+
stream->eof = 1;
356+
}
357+
} else if (nr_bytes == 0) {
358+
stream->eof = 1;
359+
}
360+
342361
_exit:
343362
#if PHP_VERSION_ID < 70400
344363
if (nr_bytes < 0) {
@@ -877,14 +896,6 @@ static int socket_set_option(php_stream *stream, int option, int value, void *pt
877896
break;
878897
}
879898
abstract->blocking = (bool) value;
880-
if (abstract->blocking) {
881-
sock->set_timeout(abstract->read_timeout, Socket::TIMEOUT_READ);
882-
sock->set_timeout(abstract->write_timeout, Socket::TIMEOUT_WRITE);
883-
} else {
884-
abstract->read_timeout = sock->get_timeout(Socket::TIMEOUT_READ);
885-
abstract->write_timeout = sock->get_timeout(Socket::TIMEOUT_WRITE);
886-
sock->set_timeout(0.001, Socket::TIMEOUT_READ | Socket::TIMEOUT_WRITE);
887-
}
888899
break;
889900
case PHP_STREAM_OPTION_XPORT_API: {
890901
return socket_xport_api(stream, sock, (php_stream_xport_param *) ptrparam STREAMS_CC);

include/swoole_socket.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -455,28 +455,26 @@ struct Socket {
455455
ssize_t sendto_blocking(const Address &dst_addr, const void *__buf, size_t __n, int flags = 0);
456456
ssize_t recvfrom_blocking(char *__buf, size_t __len, int flags, Address *sa);
457457

458-
inline ssize_t sendto(const char *dst_host, int dst_port, const void *data, size_t len, int flags = 0) {
458+
inline ssize_t sendto(const char *dst_host, int dst_port, const void *data, size_t len, int flags = 0) const {
459459
Address addr = {};
460460
if (!addr.assign(socket_type, dst_host, dst_port)) {
461461
return SW_ERR;
462462
}
463463
return sendto(addr, data, len, flags);
464464
}
465465

466-
inline ssize_t sendto(const Address &dst_addr, const void *data, size_t len, int flags) {
466+
inline ssize_t sendto(const Address &dst_addr, const void *data, size_t len, int flags) const {
467467
return ::sendto(fd, data, len, flags, &dst_addr.addr.ss, dst_addr.len);
468468
}
469469

470-
inline int catch_error(int err) {
470+
inline int catch_error(int err) const {
471471
switch (err) {
472472
case EFAULT:
473473
abort();
474474
return SW_ERROR;
475475
case EBADF:
476476
case ECONNRESET:
477-
#ifdef __CYGWIN__
478477
case ECONNABORTED:
479-
#endif
480478
case EPIPE:
481479
case ENOTCONN:
482480
case ETIMEDOUT:
@@ -489,6 +487,9 @@ struct Socket {
489487
case SW_ERROR_SSL_RESET:
490488
return SW_CLOSE;
491489
case EAGAIN:
490+
#if EAGAIN != EWOULDBLOCK
491+
case EWOULDBLOCK:
492+
#endif
492493
#ifdef HAVE_KQUEUE
493494
case ENOBUFS:
494495
#endif

tests/include/lib/src/ProcessManager.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class ProcessManager
5050
protected $childStatus = 255;
5151
protected $expectExitSignal = [0, SIGTERM];
5252
protected $parentFirst = false;
53+
protected $killed = false;
5354
/**
5455
* @var Process
5556
*/
@@ -238,7 +239,8 @@ public function kill(bool $force = false)
238239
if (!defined('PCNTL_ESRCH')) {
239240
define('PCNTL_ESRCH', 3);
240241
}
241-
if (!$this->alone && $this->childPid) {
242+
if (!$this->alone and !$this->killed and $this->childPid) {
243+
$this->killed = true;
242244
if ($force || (!@Process::kill($this->childPid) && swoole_errno() !== PCNTL_ESRCH)) {
243245
if (!@Process::kill($this->childPid, SIGKILL) && swoole_errno() !== PCNTL_ESRCH) {
244246
exit('KILL CHILD PROCESS ERROR');

tests/swoole_runtime/nonblock.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
swoole_runtime: nonblock
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../include/skipif.inc';
6+
?>
7+
--FILE--
8+
<?php
9+
require __DIR__ . '/../include/bootstrap.php';
10+
11+
Co\run(function () {
12+
$socket = stream_socket_client(
13+
'tcp://www.baidu.com:80',
14+
$errorCode,
15+
$errorMessage,
16+
1,
17+
STREAM_CLIENT_CONNECT
18+
);
19+
stream_set_timeout($socket, 5);
20+
stream_set_blocking($socket, false);
21+
$receivedData = fread($socket, 1);
22+
Assert::assert($receivedData === '');
23+
});
24+
?>
25+
--EXPECT--

tests/swoole_runtime/stream_get_meta_data.phpt

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ swoole_runtime: stream_get_meta_data
66
<?php
77
require __DIR__ . '/../include/bootstrap.php';
88

9+
use Swoole\Server;
10+
use Swoole\Runtime;
11+
912
function test($port) {
1013
$fp = stream_socket_client("tcp://127.0.0.1:".$port, $errno, $errstr, 2);
1114
if (!$fp) {
@@ -26,32 +29,26 @@ function test($port) {
2629
}
2730

2831
$pm = new ProcessManager;
29-
$pm->parentFunc = function ($pid) use ($pm)
30-
{
32+
$pm->parentFunc = function ($pid) use ($pm) {
3133
$port = $pm->getFreePort();
3234
test($port);
33-
swoole_runtime::enableCoroutine();
34-
go(function() use($port) {
35+
Runtime::setHookFlags(SWOOLE_HOOK_ALL);
36+
Co\run(function () use ($port) {
3537
test($port);
3638
});
37-
swoole_event_wait();
3839
$pm->kill();
3940
};
4041

41-
$pm->childFunc = function () use ($pm)
42-
{
43-
$serv = new \swoole_server(TCP_SERVER_HOST, $pm->getFreePort(), SWOOLE_BASE);
44-
$socket = $serv->getSocket();
42+
$pm->childFunc = function () use ($pm) {
43+
$serv = new Server(TCP_SERVER_HOST, $pm->getFreePort(), SWOOLE_BASE);
4544
$serv->set([
4645
"worker_num" => 1,
4746
'log_file' => '/dev/null',
4847
]);
49-
$serv->on("WorkerStart", function (\swoole_server $serv) use ($pm)
50-
{
48+
$serv->on("WorkerStart", function (\swoole_server $serv) use ($pm) {
5149
$pm->wakeup();
5250
});
53-
$serv->on("Receive", function (\swoole_server $serv, $fd, $rid, $data) use ($socket)
54-
{
51+
$serv->on("Receive", function (\swoole_server $serv, $fd, $rid, $data) {
5552
//donot send any
5653
});
5754
$serv->start();

0 commit comments

Comments
 (0)