Make WordPress Core

Opened 17 years ago

Closed 17 years ago

#4782 closed defect (bug) (fixed)

spawn_cron() doesn't properly consider the port of the cron.php file

Reported by: bchecketts's profile bchecketts Owned by:
Milestone: 2.3 Priority: normal
Severity: major Version:
Component: General Keywords: wp_cron, https has-patch
Focuses: Cc:


I ran into a problem today where a user would submit a new post in Wordpress, and it would cause the web server to lock up. Restarting the web server would start Apache properly, and would serve static content fine until the user requested another page from Wordpress where it would lock up again.

The configuration is a little odd, so it probably doesn't happen to many users. In order for it to occur, you have to have the "Wordpress Address" setting as a URL starting with 'https', and then write your post using a non-https URL. I tracked this down to a problem with the cron function built into wordpress. Specifically this bit of code in the spawn_cron() function in includes/cron.php

$cron_url = get_option( 'siteurl' ) . '/wp-cron.php';
        $parts = parse_url( $cron_url );

        if ($parts['scheme'] == 'https') {
                // support for SSL was added in 4.3.0
                if (version_compare(phpversion(), '4.3.0', '>=') && function_exists('openssl_open')) {
                        $argyle = @fsockopen('ssl://' . $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
                } else {
                        return false;
        } else {
                $argyle = @ fsockopen( $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01 );
        if ( $argyle )
                fputs( $argyle,
                          "GET {$parts['path']}?check=" . wp_hash('187425') . " HTTP/1.0\r\n"
                        . "Host: {$_SERVER['HTTP_HOST']}\r\n\r\n"

The line that says:

$argyle = @fsockopen('ssl://' . $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);

Assumes that you are hitting the current page on the same server/port as that returned by get_option( 'siteurl' ). Since the user was hitting the non-https version of the site, that would cause this code in the spawn_cron() function to connect to port 80 and try to establish an SSL connection. Wordpress would get that request as "\x80|\x01\x03\x01", and issue it the home page, which would, in-turn, re-run the cron function again. That sub-request would redo the same thing over, and that would continue until Apache ran out of connections. At that point it would try to request the page again, and would wait endlessly for a connection to open up, and never would.

So, to solve, I added a couple lines and made a couple changes like this:

[root@server wp-includes]# diff cron.php cron.php.original
<                       $port = isset($parts['port']) ? $parts['port'] : 443;
<                       $argyle = @fsockopen('ssl://' . $parts['host'], $port, $errno, $errstr, 0.01);
>                       $argyle = @fsockopen('ssl://' . $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
<               $port = isset($parts['port']) ? $parts['port'] : 80;
<               $argyle = @ fsockopen( $parts['host'], $port, $errno, $errstr, 0.01 );
>               $argyle = @ fsockopen( $parts['host'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01 );

That makes it consider the port of the url returned by get_option( 'siteurl' ), instead of using the port you are currently connected on. It defaults to port 443 if the url begins with https, and port 80 if not.

Attachments (1)

4782.diff (903 bytes) - added by Nazgul 17 years ago.

Download all attachments as: .zip

Change History (5)

#1 @foolswisdom
17 years ago

  • Milestone changed from 2.4 (future) to 2.3 (trunk)

17 years ago

#3 @Nazgul
17 years ago

  • Keywords has-patch added

Patch based on given code snippets attached.

#4 @ryan
17 years ago

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

(In [5972]) Take port into consideration when spawning cron. Props bchecketts. fixes #4782

Note: See TracTickets for help on using tickets.