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:
}
}
+/* 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;
/* }}} */
+/* 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)