diff options
author | Wez Furlong <wez@php.net> | 2003-05-12 23:44:48 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-05-12 23:44:48 +0000 |
commit | 6c0ee68f07462984cd65feb887dfb054bf9eff04 (patch) | |
tree | 3a7bbf708fb9cb2f19cd0790f44ef1dcb2d1c838 | |
parent | 46756f8caafe299a1f86b08034b43d98ef945d86 (diff) | |
download | php-git-6c0ee68f07462984cd65feb887dfb054bf9eff04.tar.gz |
Probable fix for #23567 - pfsockopen returns dead connection.
# Just need to verify under win32
-rw-r--r-- | ext/standard/fsock.c | 9 | ||||
-rw-r--r-- | main/network.c | 29 | ||||
-rw-r--r-- | main/php_network.h | 3 |
3 files changed, 39 insertions, 2 deletions
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index f6e47a0059..adb7d55cb9 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -160,8 +160,13 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) switch(php_stream_from_persistent_id(hashkey, &stream TSRMLS_CC)) { case PHP_STREAM_PERSISTENT_SUCCESS: - /* TODO: could check if the socket is still alive here */ - php_stream_to_zval(stream, return_value); + if (_php_network_is_stream_alive(stream)) { + php_stream_to_zval(stream, return_value); + } else { + /* it died; we need to replace it */ + php_stream_close(stream); + break; + } /* fall through */ case PHP_STREAM_PERSISTENT_FAILURE: diff --git a/main/network.c b/main/network.c index 2990ed5a1c..a25218cb6a 100644 --- a/main/network.c +++ b/main/network.c @@ -1101,6 +1101,35 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void } } +/* private API; don't use in extensions */ +int _php_network_is_stream_alive(php_stream *stream) +{ + php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; + int alive = 1; + int fd = sock->socket; + fd_set rfds; + struct timeval tv = {0, 0}; + char buf; + + /* logic: if the select call indicates that there is data to + * be read, but a read returns 0 bytes of data, then the socket + * has been closed. + */ + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + if (select(fd+1, &rfds, NULL, NULL, &tv) > 0) { + + if (FD_ISSET(fd, &rfds)) { + if (0 == recv(fd, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) { + alive = 0; + } + } + } + return alive; +} + + static int php_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; diff --git a/main/php_network.h b/main/php_network.h index 38e5ba400b..0eb09cf408 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -155,6 +155,9 @@ PHPAPI php_stream *_php_stream_sock_open_unix(const char *path, int pathlen, con /* }}} */ +/* private API; don't use in extensions */ +int _php_network_is_stream_alive(php_stream *stream); + #if HAVE_OPENSSL_EXT PHPAPI int php_stream_sock_ssl_activate_with_method(php_stream *stream, int activate, SSL_METHOD *method, php_stream *session_stream TSRMLS_DC); #define php_stream_sock_ssl_activate(stream, activate) php_stream_sock_ssl_activate_with_method((stream), (activate), SSLv23_client_method(), NULL TSRMLS_CC) |