Skip to content

Commit

Permalink
Fix missing php_error_docref, timeout_event and return value (keep sa… (
Browse files Browse the repository at this point in the history
#3383)

* Fix missing php_error_docref, timeout_event and return value (keep same with PHP netstream)

* Fix tests
  • Loading branch information
twose authored Jun 12, 2020
1 parent e949fc2 commit 83b4d13
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 29 deletions.
50 changes: 37 additions & 13 deletions swoole_runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -269,29 +269,47 @@ static size_t socket_write(php_stream *stream, const char *buf, size_t count)
static ssize_t socket_write(php_stream *stream, const char *buf, size_t count)
#endif
{
php_swoole_netstream_data_t *abstract = (php_swoole_netstream_data_t *) stream->abstract;
php_swoole_netstream_data_t *abstract;
Socket *sock;
ssize_t didwrite = -1;

abstract = (php_swoole_netstream_data_t *) stream->abstract;
if (UNEXPECTED(!abstract))
{
return 0;
goto _exit;
}
Socket *sock = (Socket*) abstract->socket;
ssize_t didwrite;

sock = (Socket*) abstract->socket;
if (UNEXPECTED(!sock))
{
return 0;
goto _exit;
}

didwrite = sock->send_all(buf, count);
if (didwrite > 0)

if (didwrite != count)
{
/* we do not expect the outer layer to continue to call the send syscall in a loop
* and didwrite is meaningless if it failed */
didwrite = -1;
abstract->stream.timeout_event = (sock->errCode == ETIMEDOUT);
php_error_docref(
NULL, E_NOTICE, "Send of " ZEND_LONG_FMT " bytes failed with errno=%d %s",
(zend_long) count, sock->errCode, sock->errMsg
);
}
else
{
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), didwrite, 0);
}

_exit:
#if PHP_VERSION_ID < 70400
if (didwrite < 0)
{
didwrite = 0;
}
#endif

return didwrite;
}

Expand All @@ -301,18 +319,24 @@ static size_t socket_read(php_stream *stream, char *buf, size_t count)
static ssize_t socket_read(php_stream *stream, char *buf, size_t count)
#endif
{
php_swoole_netstream_data_t *abstract = (php_swoole_netstream_data_t *) stream->abstract;
php_swoole_netstream_data_t *abstract;
Socket *sock;
ssize_t nr_bytes = -1;

abstract = (php_swoole_netstream_data_t *) stream->abstract;
if (UNEXPECTED(!abstract))
{
return 0;
goto _exit;
}
Socket *sock = (Socket*) abstract->socket;
ssize_t nr_bytes = 0;

sock = (Socket*) abstract->socket;
if (UNEXPECTED(!sock))
{
return 0;
goto _exit;
}

nr_bytes = sock->recv(buf, count);

/**
* sock->errCode != ETIMEDOUT : Compatible with sync blocking IO
*/
Expand All @@ -322,13 +346,13 @@ static ssize_t socket_read(php_stream *stream, char *buf, size_t count)
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
}

_exit:
#if PHP_VERSION_ID < 70400
if (nr_bytes < 0)
{
nr_bytes = 0;
}
#endif

return nr_bytes;
}

Expand Down
20 changes: 10 additions & 10 deletions tests/swoole_feature/cross_close/php_stream_full_duplex.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,38 @@ $pm = new ProcessManager();
$pm->parentFunc = function () use ($pm) {
go(function () use ($pm) {
$cli = stream_socket_client("tcp://127.0.0.1:{$pm->getFreePort()}", $errno, $errstr, 1);
Assert::assert(!$errno);
Assert::true(!$errno);
go(function () use ($pm, $cli) {
Co::sleep(0.001);
echo "CLOSE\n";
Assert::assert(fclose($cli));
Assert::true(fclose($cli));
// double close
Assert::assert(!@fclose($cli));
Assert::true(!@fclose($cli));
$pm->kill();
echo "DONE\n";
});
go(function () use ($cli) {
echo "SEND\n";
$size = 64 * 1024 * 1024;
Assert::assert(fwrite($cli, str_repeat('S', $size)) < $size);
Assert::assert(!@fclose($cli));
Assert::true(@fwrite($cli, str_repeat('S', $size)) < $size);
Assert::true(!@fclose($cli));
echo "SEND CLOSED\n";
});
go(function () use ($cli) {
echo "RECV\n";
Assert::assert(empty(fread($cli, 8192)));
Assert::assert(!@fclose($cli));
Assert::true(empty(fread($cli, 8192)));
Assert::true(!@fclose($cli));
echo "RECV CLOSED\n";
});
});
};
$pm->childFunc = function () use ($pm) {
go(function () use ($pm) {
$server = new Co\Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
Assert::assert($server->bind('127.0.0.1', $pm->getFreePort()));
Assert::assert($server->listen());
Assert::true($server->bind('127.0.0.1', $pm->getFreePort()));
Assert::true($server->listen());
go(function () use ($pm, $server) {
if (Assert::assert(($conn = $server->accept()) && $conn instanceof Co\Socket)) {
if (Assert::true(($conn = $server->accept()) && $conn instanceof Co\Socket)) {
switch_process();
co::sleep(5);
$conn->close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ $pm = new ProcessManager();
$pm->parentFunc = function () use ($pm) {
go(function () use ($pm) {
$cli = stream_socket_client("tcp://127.0.0.1:{$pm->getFreePort()}", $errno, $errstr, 1);
Assert::assert(!$errno);
Assert::true(!$errno);
go(function () use ($cli) {
echo "SEND\n";
$size = 64 * 1024 * 1024;
Assert::assert(fwrite($cli, str_repeat('S', $size)) < $size);
Assert::true(@fwrite($cli, str_repeat('S', $size)) < $size);
echo "SEND CLOSED\n";
});
go(function () use ($cli) {
echo "RECV\n";
Assert::assert(!fread($cli, 8192));
Assert::true(!fread($cli, 8192));
echo "RECV CLOSED\n";
});
$pm->wakeup();
Expand All @@ -30,10 +30,10 @@ $pm->parentFunc = function () use ($pm) {
$pm->childFunc = function () use ($pm) {
go(function () use ($pm) {
$server = new Co\Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
Assert::assert($server->bind('127.0.0.1', $pm->getFreePort()));
Assert::assert($server->listen());
Assert::true($server->bind('127.0.0.1', $pm->getFreePort()));
Assert::true($server->listen());
go(function () use ($pm, $server) {
if (Assert::assert(($conn = $server->accept()) && $conn instanceof Co\Socket)) {
if (Assert::true(($conn = $server->accept()) && $conn instanceof Co\Socket)) {
$pm->wait();
echo "CLOSE\n";
$conn->close();
Expand Down

0 comments on commit 83b4d13

Please sign in to comment.