From bfd975d26ab51152ac6a256827ffda93b15df48b Mon Sep 17 00:00:00 2001
From: Andreas Gohr <andi@splitbrain.org>
Date: Tue, 6 Nov 2012 20:58:38 +0100
Subject: [PATCH] fix regression bug in HTTPClient FS#2621

In the recent refactoring of the HTTPClient, a problem with certain
systems was reintroduced. On these systems a select() call always
waits for a timeout on the first call before working properly on the
second call.

This patch reintroduces the shorter timeouts with usleep rate limiting
again.

Since this bug is not reproducible on other systems it can't be unit
tested unfortunately.
---
 inc/HTTPClient.php | 54 ++++++++++++++++++++++------------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

diff --git a/inc/HTTPClient.php b/inc/HTTPClient.php
index a25846c31..c4cfcbf7c 100644
--- a/inc/HTTPClient.php
+++ b/inc/HTTPClient.php
@@ -509,15 +509,17 @@ class HTTPClient {
             if(feof($socket))
                 throw new HTTPClientException("Socket disconnected while writing $message");
 
-            // wait for stream ready or timeout
-            self::selecttimeout($this->timeout - $time_used, $sec, $usec);
-            if(@stream_select($sel_r, $sel_w, $sel_e, $sec, $usec) !== false){
-                // write to stream
-                $nbytes = fwrite($socket, substr($data,$written,4096));
-                if($nbytes === false)
-                    throw new HTTPClientException("Failed writing to socket while sending $message", -100);
-                $written += $nbytes;
+            // wait for stream ready or timeout (1sec)
+            if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
+                 usleep(1000);
+                 continue;
             }
+
+            // write to stream
+            $nbytes = fwrite($socket, substr($data,$written,4096));
+            if($nbytes === false)
+                throw new HTTPClientException("Failed writing to socket while sending $message", -100);
+            $written += $nbytes;
         }
     }
 
@@ -556,15 +558,17 @@ class HTTPClient {
             }
 
             if ($to_read > 0) {
-                // wait for stream ready or timeout
-                self::selecttimeout($this->timeout - $time_used, $sec, $usec);
-                if(@stream_select($sel_r, $sel_w, $sel_e, $sec, $usec) !== false){
-                    $bytes = fread($socket, $to_read);
-                    if($bytes === false)
-                        throw new HTTPClientException("Failed reading from socket while reading $message", -100);
-                    $r_data .= $bytes;
-                    $to_read -= strlen($bytes);
+                // wait for stream ready or timeout (1sec)
+                if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
+                     usleep(1000);
+                     continue;
                 }
+
+                $bytes = fread($socket, $to_read);
+                if($bytes === false)
+                    throw new HTTPClientException("Failed reading from socket while reading $message", -100);
+                $r_data .= $bytes;
+                $to_read -= strlen($bytes);
             }
         } while ($to_read > 0 && strlen($r_data) < $nbytes);
         return $r_data;
@@ -595,11 +599,13 @@ class HTTPClient {
             if(feof($socket))
                 throw new HTTPClientException("Premature End of File (socket) while reading $message");
 
-            // wait for stream ready or timeout
-            self::selecttimeout($this->timeout - $time_used, $sec, $usec);
-            if(@stream_select($sel_r, $sel_w, $sel_e, $sec, $usec) !== false){
-                $r_data = fgets($socket, 1024);
+            // wait for stream ready or timeout (1sec)
+            if(@stream_select($sel_r,$sel_w,$sel_e,1) === false){
+                 usleep(1000);
+                 continue;
             }
+
+            $r_data = fgets($socket, 1024);
         } while (!preg_match('/\n$/',$r_data));
         return $r_data;
     }
@@ -629,14 +635,6 @@ class HTTPClient {
         return ((float)$usec + (float)$sec);
     }
 
-    /**
-     * Calculate seconds and microseconds
-     */
-    static function selecttimeout($time, &$sec, &$usec){
-        $sec = floor($time);
-        $usec = (int)(($time - $sec) * 1000000);
-    }
-
     /**
      * convert given header string to Header array
      *
-- 
GitLab