From c18d58b97c875df90e8092cc34a1e51e8bad6d87 Mon Sep 17 00:00:00 2001 From: Shafreeck Sea Date: Wed, 5 Aug 2015 03:03:23 +0000 Subject: [PATCH] Work around PHP bug of liveness checking --- library.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/library.c b/library.c index b5f10de24a..6dd5146942 100644 --- a/library.c +++ b/library.c @@ -140,6 +140,21 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock, int no_throw TSRMLS_DC) return -1; } + /* NOITCE: set errno = 0 here + * + * There is a bug in php socket stream to check liveness of a connection: + * if (0 >= recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EWOULDBLOCK) { + * alive = 0; + * } + * If last errno is EWOULDBLOCK and recv returns 0 because of connection closed, alive would not be + * set to 0. However, the connection is close indeed. The php_stream_eof is not reliable. This will + * cause a "read error on connection" exception when use a closed persistent connection. + * + * We work around this by set errno = 0 first. + * + * Bug fix of php: https://github.com/php/php-src/pull/1456 + * */ + errno = 0; eof = php_stream_eof(redis_sock->stream); for (; eof; count++) { if((MULTI == redis_sock->mode) || redis_sock->watching || count == 10) { @@ -171,6 +186,7 @@ PHP_REDIS_API int redis_check_eof(RedisSock *redis_sock, int no_throw TSRMLS_DC) } redis_sock_connect(redis_sock TSRMLS_CC); /* reconnect */ if(redis_sock->stream) { /* check for EOF again. */ + errno = 0; eof = php_stream_eof(redis_sock->stream); } }