|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75288 stream_socket_enable_crypto() blocks during handshake
Submitted: 2017-09-29 19:10 UTC Modified: 2022-10-05 20:20 UTC
Avg. Score:4.0 ± 1.4
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: james at jamesreno dot com Assigned:
Status: Open Package: OpenSSL related
PHP Version: 7.0.24 OS: Ubuntu 16.04
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Bug Type:
From: james at jamesreno dot com
New email:
PHP Version: OS:


 [2017-09-29 19:10 UTC] james at jamesreno dot com
When enabling ssl on a socket with php 7.0.24 the handshake blocks the socket. I expect the enable_crypto to immediately return "0" if the socket is in non-blocking mode and there is not enough data available to perform the handshake.

Test script:
$ssl_stream_ctx = stream_context_create(array(
	'ssl' => array(
		'local_cert'	=> 'cert.pem',
		'verify_peer'	=> FALSE,

$listener = @stream_socket_server("tcp://",$errno,$errstr,STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $ssl_stream_ctx);
stream_set_blocking($listener, FALSE);
$peerName = FALSE;
$sock = @stream_socket_accept($fd, 0.01, $peerName);
stream_set_blocking($sock, FALSE);
$data = stream_socket_recvfrom($sock,1,STREAM_PEEK);
if ($data[0] == "\x16") {
	$sslInitStartTime = microtime(TRUE);
	$ret = stream_socket_enable_crypto($sock, TRUE, STREAM_CRYPTO_METHOD_SSLv23_SERVER);
	$sslInitEndTime = microtime(TRUE);
	$sslInitTime = $sslInitEndTime - $sslInitStartTime;
	if ($sslInitTime >= 0.1) {


Expected result:
Expect to return immediately and not hange > 0.1sec

Actual result:
Script hangs sometimes up to several seconds with "far away high-latency" clients.


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2017-09-29 19:15 UTC] james at jamesreno dot com
Might be related to the fix for one of the following bugs:
- bug#72333: fwrite() on non-blocking SSL sockets doesn't work
- bug#45808: stream_socket_enable_crypto() blocks during handshake
 [2017-09-29 21:38 UTC] james at jamesreno dot com
in ext/openssl/xp_ssl.c there is a line:

has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);

From what I can gather this means that if a socket timeout is specified in the php.ini/config and then non-blocking is enabled the socket will WAIT upto a maximum of the default time and will hang a non-blocking socket due to the if (has_timeout) {} checking.

                                        if (has_timeout) {
                                                left_time = subtract_timeval( *timeout, elapsed_time );
                                        php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
                                                (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);

This is passed through to php_pollfd_for() instead of NULL which causes the non-blocking socket to "block".  I believe if blocking is set, this part should ALWAYS be passed NULL so

the line that reads:

                                        php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
                                                (POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);

Should be changed to:

                                        php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
                                                (POLLIN|POLLPRI) : POLLOUT, !blocked && has_timeout ? &left_time : NULL);
 [2022-10-05 20:20 UTC]
-Package: Streams related +Package: OpenSSL related
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Jul 23 21:01:28 2024 UTC