summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2003-05-12 23:44:48 +0000
committerWez Furlong <wez@php.net>2003-05-12 23:44:48 +0000
commit6c0ee68f07462984cd65feb887dfb054bf9eff04 (patch)
tree3a7bbf708fb9cb2f19cd0790f44ef1dcb2d1c838
parent46756f8caafe299a1f86b08034b43d98ef945d86 (diff)
downloadphp-git-6c0ee68f07462984cd65feb887dfb054bf9eff04.tar.gz
Probable fix for #23567 - pfsockopen returns dead connection.
# Just need to verify under win32
-rw-r--r--ext/standard/fsock.c9
-rw-r--r--main/network.c29
-rw-r--r--main/php_network.h3
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)