Making WordPress.org

Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#1104 closed defect (bug) (invalid)

WP_Http::request hangs on badly behaving servers

Reported by: lutz-donnerhacke's profile Lutz Donnerhacke Owned by:
Milestone: Priority: normal
Component: General Keywords: has-patch needs-testing
Cc:

Description

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).

Change History (2)

#1 @samuelsidler
9 years ago

  • Resolution set to invalid
  • Status changed from new to closed

Hello,

It seems you've filed a ticket here on the meta trac but meant to file it on core trac. This trac is for issues with WordPress.org and its related sites, not for issues with the WordPress core project. Please file your ticket on the core trac.

Note: See TracTickets for help on using tickets.