From cbf133667db1f7235456c5bef105bfe9cafb049b Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 24 Sep 2026 13:11:27 +0500 Subject: [PATCH 1/5] Fix GH-23879: Do not report AcceptFailed on non-blocking accept timeout --- NEWS | 2 ++ ext/openssl/xp_ssl.c | 4 +++ ext/standard/streamsfuncs.c | 10 ++++--- ext/standard/tests/streams/gh23879.phpt | 36 +++++++++++++++++++++++++ main/network.c | 2 -- main/php_network.h | 2 ++ main/streams/xp_socket.c | 4 +++ 7 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 ext/standard/tests/streams/gh23879.phpt diff --git a/NEWS b/NEWS index 2595e055ddfe..ebaff51b9572 100644 --- a/NEWS +++ b/NEWS @@ -85,6 +85,8 @@ PHP NEWS - Streams: . Applied the so_linger, so_rcvbuf and so_sndbuf context options to unix sockets. (David Carlier) + . Fixed bug GH-23879 (stream_socket_accept() reports AcceptFailed when a + non-blocking listener has no pending connection). (Lazizbek Ergashev) - Standard: . Fixed bug #60110 (fclose(), file_put_contents(), copy() do not return false diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 59be6503e00c..3c58829a64c0 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -3557,6 +3557,10 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ } } } + } else if (!sock->s.is_blocked && (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE + || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code))) { + /* No pending connection is not an error for a non-blocking listener. */ + return 0; } return xparam->outputs.client == NULL ? -1 : 0; diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 6502ac279e26..636424b39197 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -314,11 +314,13 @@ PHP_FUNCTION(stream_socket_accept) php_stream_error_operation_begin(); - if (0 == php_stream_xport_accept(stream, &clistream, + int ret = php_stream_xport_accept(stream, &clistream, zpeername ? &peername : NULL, NULL, NULL, tv_pointer, &errstr - ) && clistream) { + ); + + if (0 == ret && clistream) { if (peername) { ZEND_TRY_ASSIGN_REF_STR(zpeername, peername); @@ -328,7 +330,9 @@ PHP_FUNCTION(stream_socket_accept) if (peername) { zend_string_release(peername); } - php_stream_warn(stream, AcceptFailed, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); + if (0 != ret) { + php_stream_warn(stream, AcceptFailed, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); + } RETVAL_FALSE; } diff --git a/ext/standard/tests/streams/gh23879.phpt b/ext/standard/tests/streams/gh23879.phpt new file mode 100644 index 000000000000..2b605efbb881 --- /dev/null +++ b/ext/standard/tests/streams/gh23879.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-23879 (stream_socket_accept() reports AcceptFailed when a non-blocking listener has no pending connection) +--FILE-- + [ + 'error_mode' => StreamErrorMode::Exception, + 'error_store' => StreamErrorStore::All, + ], + ]), +); +stream_set_blocking($server, false); + +var_dump(stream_socket_accept($server, 0)); +var_dump(stream_last_errors()); + +$client = stream_socket_client('tcp://' . stream_socket_get_name($server, false)); +var_dump(is_resource(stream_socket_accept($server, 1))); +var_dump(stream_socket_accept($server, 0)); + +stream_set_blocking($server, true); +try { + stream_socket_accept($server, 0); +} catch (StreamException $e) { + var_dump($e->getErrors()[0]->code); +} +?> +--EXPECT-- +bool(false) +array(0) { +} +bool(true) +bool(false) +enum(StreamErrorCode::AcceptFailed) diff --git a/main/network.c b/main/network.c index 1eee7390a23a..850e079ddae1 100644 --- a/main/network.c +++ b/main/network.c @@ -69,7 +69,6 @@ # include "win32/time.h" # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR -# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT #ifdef HAVE_IPV6 const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */ @@ -78,7 +77,6 @@ const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */ #else # define SOCK_ERR -1 # define SOCK_CONN_ERR -1 -# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT #endif #ifdef HAVE_GETADDRINFO diff --git a/main/php_network.h b/main/php_network.h index 5c2cb0acede2..6782a965d6a2 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -109,10 +109,12 @@ typedef int php_socket_t; # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR # define SOCK_RECV_ERR SOCKET_ERROR +# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT #else # define SOCK_ERR -1 # define SOCK_CONN_ERR -1 # define SOCK_RECV_ERR -1 +# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT #endif #define STREAM_SOCKOP_NONE (1 << 0) diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 6c408dab1127..cb9b621b30d2 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -1078,6 +1078,10 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t GC_ADDREF(stream->ctx); } } + } else if (!sock->is_blocked && (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE + || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code))) { + /* No pending connection is not an error for a non-blocking listener. */ + return 0; } return xparam->outputs.client == NULL ? -1 : 0; From 44b7740a2958dfebcc590191e5d2f75df4fd2e74 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 24 Sep 2026 15:06:25 +0500 Subject: [PATCH 2/5] Document the php_stream_xport_accept() change in UPGRADING.INTERNALS --- UPGRADING.INTERNALS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index efcf9c00544e..1c1bce27eb1b 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -45,6 +45,9 @@ PHP 8.7 INTERNALS UPGRADE NOTES - The INIT_CLASS_ENTRY_INIT_METHODS() macro, which was previously used as part of handling disabled classes, was removed following the removal of the `disable_classes` INI setting in PHP 8.5. +- php_stream_xport_accept() now returns 0 with a NULL client when no + connection is pending before the timeout. Callers must check the client, + not only the return value. ======================== 2. Build system changes From 5178927a132ee1952c102d431b47c7c63a3a0df2 Mon Sep 17 00:00:00 2001 From: lazerg Date: Sun, 4 Oct 2026 23:30:59 +0500 Subject: [PATCH 3/5] Do not report AcceptFailed on accept timeout for blocking listeners either --- NEWS | 4 ++-- UPGRADING | 2 ++ ext/openssl/xp_ssl.c | 6 +++--- ext/standard/tests/streams/gh23879.phpt | 13 ++++++------- main/streams/xp_socket.c | 6 +++--- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index ebaff51b9572..cf5daabd3a27 100644 --- a/NEWS +++ b/NEWS @@ -85,8 +85,8 @@ PHP NEWS - Streams: . Applied the so_linger, so_rcvbuf and so_sndbuf context options to unix sockets. (David Carlier) - . Fixed bug GH-23879 (stream_socket_accept() reports AcceptFailed when a - non-blocking listener has no pending connection). (Lazizbek Ergashev) + . stream_socket_accept() no longer reports AcceptFailed on a timeout with no + pending connection (GH-23879). (Lazizbek Ergashev) - Standard: . Fixed bug #60110 (fclose(), file_put_contents(), copy() do not return false diff --git a/UPGRADING b/UPGRADING index a6cdf9829ab1..476c652c3860 100644 --- a/UPGRADING +++ b/UPGRADING @@ -28,6 +28,8 @@ PHP 8.7 UPGRADE NOTES . The number of filters that can be chained in a php://filter URL is limited to 16 by default. Set the stream context option max_filter_count to change this. + . stream_socket_accept() no longer reports an AcceptFailed error when no + connection is pending before the timeout. It still returns false. ======================================== 2. New Features diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 3c58829a64c0..2b1fccb5e154 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -3557,9 +3557,9 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ } } } - } else if (!sock->s.is_blocked && (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE - || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code))) { - /* No pending connection is not an error for a non-blocking listener. */ + } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE + || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { + /* No pending connection within the timeout is not an error. */ return 0; } diff --git a/ext/standard/tests/streams/gh23879.phpt b/ext/standard/tests/streams/gh23879.phpt index 2b605efbb881..56301367dd8f 100644 --- a/ext/standard/tests/streams/gh23879.phpt +++ b/ext/standard/tests/streams/gh23879.phpt @@ -1,5 +1,5 @@ --TEST-- -GH-23879 (stream_socket_accept() reports AcceptFailed when a non-blocking listener has no pending connection) +GH-23879 (stream_socket_accept() reports AcceptFailed when no connection is pending) --FILE-- getErrors()[0]->code); -} +var_dump(stream_socket_accept($server, 0.1)); +var_dump(stream_last_errors()); ?> --EXPECT-- bool(false) @@ -33,4 +30,6 @@ array(0) { } bool(true) bool(false) -enum(StreamErrorCode::AcceptFailed) +bool(false) +array(0) { +} diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index cb9b621b30d2..3ce50c182d75 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -1078,9 +1078,9 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t GC_ADDREF(stream->ctx); } } - } else if (!sock->is_blocked && (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE - || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code))) { - /* No pending connection is not an error for a non-blocking listener. */ + } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE + || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { + /* No pending connection within the timeout is not an error. */ return 0; } From 1cd44708d111f1c882da7a84d6a30466006046d0 Mon Sep 17 00:00:00 2001 From: lazerg Date: Mon, 5 Oct 2026 07:40:53 +0500 Subject: [PATCH 4/5] Only ignore a zero accept timeout and report others as TimeOut --- NEWS | 5 +++-- UPGRADING | 5 +++-- ext/openssl/xp_ssl.c | 2 +- ext/standard/streamsfuncs.c | 2 ++ ext/standard/tests/streams/gh23879.phpt | 16 +++++++++++----- main/streams/xp_socket.c | 2 +- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index cf5daabd3a27..0d38958818ef 100644 --- a/NEWS +++ b/NEWS @@ -85,8 +85,9 @@ PHP NEWS - Streams: . Applied the so_linger, so_rcvbuf and so_sndbuf context options to unix sockets. (David Carlier) - . stream_socket_accept() no longer reports AcceptFailed on a timeout with no - pending connection (GH-23879). (Lazizbek Ergashev) + . stream_socket_accept() no longer reports an error on a zero timeout with no + pending connection and reports TimeOut instead of AcceptFailed on other + timeouts (GH-23879). (Lazizbek Ergashev) - Standard: . Fixed bug #60110 (fclose(), file_put_contents(), copy() do not return false diff --git a/UPGRADING b/UPGRADING index 476c652c3860..7cdc3b5f9fbc 100644 --- a/UPGRADING +++ b/UPGRADING @@ -28,8 +28,9 @@ PHP 8.7 UPGRADE NOTES . The number of filters that can be chained in a php://filter URL is limited to 16 by default. Set the stream context option max_filter_count to change this. - . stream_socket_accept() no longer reports an AcceptFailed error when no - connection is pending before the timeout. It still returns false. + . stream_socket_accept() no longer reports an error when the timeout is 0 + and no connection is pending. It still returns false. When a non-zero + timeout expires, the error code is now TimeOut instead of AcceptFailed. ======================================== 2. New Features diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 2b1fccb5e154..5217e732a938 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -3559,7 +3559,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ } } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { - /* No pending connection within the timeout is not an error. */ + /* No pending connection, the caller decides how to report it. */ return 0; } diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 636424b39197..bc27e694589a 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -332,6 +332,8 @@ PHP_FUNCTION(stream_socket_accept) } if (0 != ret) { php_stream_warn(stream, AcceptFailed, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); + } else if (!tv_pointer || tv.tv_sec || tv.tv_usec) { + php_stream_warn(stream, TimeOut, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); } RETVAL_FALSE; } diff --git a/ext/standard/tests/streams/gh23879.phpt b/ext/standard/tests/streams/gh23879.phpt index 56301367dd8f..913df19e283a 100644 --- a/ext/standard/tests/streams/gh23879.phpt +++ b/ext/standard/tests/streams/gh23879.phpt @@ -21,15 +21,21 @@ var_dump(is_resource(stream_socket_accept($server, 1))); var_dump(stream_socket_accept($server, 0)); stream_set_blocking($server, true); -var_dump(stream_socket_accept($server, 0.1)); -var_dump(stream_last_errors()); +var_dump(stream_socket_accept($server, 0)); + +try { + stream_socket_accept($server, 0.1); +} catch (StreamException $e) { + echo $e->getMessage(), "\n"; + echo $e->getErrors()[0]->code->name, "\n"; +} ?> ---EXPECT-- +--EXPECTF-- bool(false) array(0) { } bool(true) bool(false) bool(false) -array(0) { -} +Accept failed: %s +TimeOut diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 3ce50c182d75..a20d4f833565 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -1080,7 +1080,7 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t } } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { - /* No pending connection within the timeout is not an error. */ + /* No pending connection, the caller decides how to report it. */ return 0; } From d1bfd8e3ebb7c5ce91cdc3c10d87e6219d37a8d0 Mon Sep 17 00:00:00 2001 From: lazerg Date: Thu, 8 Oct 2026 19:38:58 +0500 Subject: [PATCH 5/5] Check for a pending connection in stream_socket_accept() instead of the transports --- NEWS | 3 +-- UPGRADING | 3 +-- UPGRADING.INTERNALS | 3 --- ext/openssl/xp_ssl.c | 4 ---- ext/standard/streamsfuncs.c | 17 ++++++++--------- ext/standard/tests/streams/gh23879.phpt | 2 +- main/network.c | 2 ++ main/php_network.h | 2 -- main/streams/xp_socket.c | 4 ---- 9 files changed, 13 insertions(+), 27 deletions(-) diff --git a/NEWS b/NEWS index 0d38958818ef..40209f92bf99 100644 --- a/NEWS +++ b/NEWS @@ -86,8 +86,7 @@ PHP NEWS . Applied the so_linger, so_rcvbuf and so_sndbuf context options to unix sockets. (David Carlier) . stream_socket_accept() no longer reports an error on a zero timeout with no - pending connection and reports TimeOut instead of AcceptFailed on other - timeouts (GH-23879). (Lazizbek Ergashev) + pending connection (GH-23879). (Lazizbek Ergashev) - Standard: . Fixed bug #60110 (fclose(), file_put_contents(), copy() do not return false diff --git a/UPGRADING b/UPGRADING index 7cdc3b5f9fbc..67a462c4c964 100644 --- a/UPGRADING +++ b/UPGRADING @@ -29,8 +29,7 @@ PHP 8.7 UPGRADE NOTES to 16 by default. Set the stream context option max_filter_count to change this. . stream_socket_accept() no longer reports an error when the timeout is 0 - and no connection is pending. It still returns false. When a non-zero - timeout expires, the error code is now TimeOut instead of AcceptFailed. + and no connection is pending. It still returns false. ======================================== 2. New Features diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index 1c1bce27eb1b..efcf9c00544e 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -45,9 +45,6 @@ PHP 8.7 INTERNALS UPGRADE NOTES - The INIT_CLASS_ENTRY_INIT_METHODS() macro, which was previously used as part of handling disabled classes, was removed following the removal of the `disable_classes` INI setting in PHP 8.5. -- php_stream_xport_accept() now returns 0 with a NULL client when no - connection is pending before the timeout. Callers must check the client, - not only the return value. ======================== 2. Build system changes diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 5217e732a938..59be6503e00c 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -3557,10 +3557,6 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ } } } - } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE - || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { - /* No pending connection, the caller decides how to report it. */ - return 0; } return xparam->outputs.client == NULL ? -1 : 0; diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index bc27e694589a..e9d7345a1bf4 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -314,13 +314,16 @@ PHP_FUNCTION(stream_socket_accept) php_stream_error_operation_begin(); - int ret = php_stream_xport_accept(stream, &clistream, + php_socket_t fd; + if (tv_pointer && tv.tv_sec == 0 && tv.tv_usec == 0 + && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&fd, 0) + && fd != SOCK_ERR && php_pollfd_for_ms(fd, PHP_POLLREADABLE, 0) == 0) { + RETVAL_FALSE; + } else if (0 == php_stream_xport_accept(stream, &clistream, zpeername ? &peername : NULL, NULL, NULL, tv_pointer, &errstr - ); - - if (0 == ret && clistream) { + ) && clistream) { if (peername) { ZEND_TRY_ASSIGN_REF_STR(zpeername, peername); @@ -330,11 +333,7 @@ PHP_FUNCTION(stream_socket_accept) if (peername) { zend_string_release(peername); } - if (0 != ret) { - php_stream_warn(stream, AcceptFailed, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); - } else if (!tv_pointer || tv.tv_sec || tv.tv_usec) { - php_stream_warn(stream, TimeOut, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); - } + php_stream_warn(stream, AcceptFailed, "Accept failed: %s", errstr ? ZSTR_VAL(errstr) : "Unknown error"); RETVAL_FALSE; } diff --git a/ext/standard/tests/streams/gh23879.phpt b/ext/standard/tests/streams/gh23879.phpt index 913df19e283a..fe6fe0dddc12 100644 --- a/ext/standard/tests/streams/gh23879.phpt +++ b/ext/standard/tests/streams/gh23879.phpt @@ -38,4 +38,4 @@ bool(true) bool(false) bool(false) Accept failed: %s -TimeOut +AcceptFailed diff --git a/main/network.c b/main/network.c index 850e079ddae1..1eee7390a23a 100644 --- a/main/network.c +++ b/main/network.c @@ -69,6 +69,7 @@ # include "win32/time.h" # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR +# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT #ifdef HAVE_IPV6 const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */ @@ -77,6 +78,7 @@ const struct in6_addr in6addr_any = {0}; /* IN6ADDR_ANY_INIT; */ #else # define SOCK_ERR -1 # define SOCK_CONN_ERR -1 +# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT #endif #ifdef HAVE_GETADDRINFO diff --git a/main/php_network.h b/main/php_network.h index 6782a965d6a2..5c2cb0acede2 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -109,12 +109,10 @@ typedef int php_socket_t; # define SOCK_ERR INVALID_SOCKET # define SOCK_CONN_ERR SOCKET_ERROR # define SOCK_RECV_ERR SOCKET_ERROR -# define PHP_TIMEOUT_ERROR_VALUE WSAETIMEDOUT #else # define SOCK_ERR -1 # define SOCK_CONN_ERR -1 # define SOCK_RECV_ERR -1 -# define PHP_TIMEOUT_ERROR_VALUE ETIMEDOUT #endif #define STREAM_SOCKOP_NONE (1 << 0) diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index a20d4f833565..6c408dab1127 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -1078,10 +1078,6 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t GC_ADDREF(stream->ctx); } } - } else if (xparam->outputs.error_code == PHP_TIMEOUT_ERROR_VALUE - || PHP_IS_TRANSIENT_ERROR(xparam->outputs.error_code)) { - /* No pending connection, the caller decides how to report it. */ - return 0; } return xparam->outputs.client == NULL ? -1 : 0;