[wp-meta] [Making WordPress.org] #1104: WP_Http::request hangs on badly behaving servers

Making WordPress.org noreply at wordpress.org
Wed Jul 8 16:12:00 UTC 2015


#1104: WP_Http::request hangs on badly behaving servers
------------------------------------+---------------------
Reporter:  Lutz Donnerhacke         |      Owner:
    Type:  defect                   |     Status:  new
Priority:  normal                   |  Component:  General
Keywords:  has-patch needs-testing  |
------------------------------------+---------------------
 Some plugin includes a call to "fetch_feed( 'https://wpml.org/feed/' )"
 which takes 300 seconds to complete. The whole backend hangs during this
 rending of the dashboard widget.

 Tracing the problem down reveals, that the function WP_Http::request has a
 problem with the response from the server.

 The server does answer the HTTP/1.0 request with an HTTP/1.1 response and
 300 seconds timeout:
 {{{
 $ openssl s_client -connect wpml.org:443
 SSL-Session:
     Protocol  : TLSv1
     Cipher    : DHE-RSA-AES128-SHA
     Session-ID: 45...30
     Session-ID-ctx:
     Master-Key: 68...4F
     Key-Arg   : None
     Start Time: 1436367230
     Timeout   : 300 (sec)
 ---
 GET /feed/ HTTP/1.0
 Host: wpml.org

 HTTP/1.1 302 Found
 ...
 [300 seconds to wait until the server closes the connection]
 }}}
 The WP_Http::request function does not handle this case correctly.
 It located in this part of the code:
 {{{
    $header_length = 0;
    while ( ! feof( $handle ) && $keep_reading ) {
       $block = fread( $handle, $block_size );
       $strResponse .= $block;
       if ( ! $bodyStarted && strpos( $strResponse, ...
          $header_length = strpos( $strResponse, ...
          $bodyStarted = true;
       }
       $keep_reading = ( ! $bodyStarted || !...
    }
 }}}
 fread() waits the default 10s timeout and returns nothing (after the
 initial two reads). The repeats 30 times accumulating to 300 seconds.
 {{{
 Count     Avg.Time     Tot.Time Name (linenumbers differ from the
 original)
     1   301.201028   301.201028 wp-includes/class-http.php:889
     1     0.595707     0.595707 -> 1065
     1     0.000048     0.000048 -> 1067
     1     0.000008     0.000008 -> 1075
     1     0.000007     0.000007 -> 1084
     1     0.000006     0.000006 -> 1131
    32     0.000033     0.001070 -> 1134
    32     9.386880   300.380167 -> 1136
     1     0.000025     0.000025 -> 1145
     1     0.000030     0.000030 -> 1148
     1     0.000109     0.000109 -> 1153
 }}}
 The obvious solution is to stop reading if nothing is returned.
 {{{
    $header_length = 0;
    while ( ! feof( $handle ) && $keep_reading ) {
       $block = fread( $handle, $block_size );
       $strResponse .= $block;
       if ( ! $bodyStarted && strpos( $strResponse, ...
          $header_length = strpos( $strResponse, ...
          $bodyStarted = true;
       }
       $keep_reading = ( ! $bodyStarted || !...
 +     if(strlen($block) === 0) break;
    }
 }}}

 This solves the problem for the badly behaving servers (in this case the
 one from the plugin).

--
Ticket URL: <https://meta.trac.wordpress.org/ticket/1104>
Making WordPress.org <https://meta.trac.wordpress.org/>
Making WordPress.org


More information about the wp-meta mailing list