]> granicus.if.org Git - php/commitdiff
Probable fix for #23567 - pfsockopen returns dead connection.
authorWez Furlong <wez@php.net>
Mon, 12 May 2003 23:44:48 +0000 (23:44 +0000)
committerWez Furlong <wez@php.net>
Mon, 12 May 2003 23:44:48 +0000 (23:44 +0000)
# Just need to verify under win32

ext/standard/fsock.c
main/network.c
main/php_network.h

index f6e47a0059b12bf5ed819f691441870a906a8fce..adb7d55cb9e4161e93995dca4f879d32ccd8f21f 100644 (file)
@@ -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:
index 2990ed5a1c85de1093da661efd950e411d8ee4e1..a25218cb6ab07ff68d882c571b85863c3e4893f3 100644 (file)
@@ -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;
index 38e5ba400b1acd0898f7786944f2cf092bff1b27..0eb09cf4082ddcc68885e56953fe900bbf6f6218 100644 (file)
@@ -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)