[wp-trac] [WordPress Trac] #4782: spawn_cron() doesn't properly
consider the port of the cron.php file
WordPress Trac
wp-trac at lists.automattic.com
Mon Aug 20 18:09:21 GMT 2007
#4782: spawn_cron() doesn't properly consider the port of the cron.php file
------------------------+---------------------------------------------------
Reporter: bchecketts | Owner: anonymous
Type: defect | Status: new
Priority: normal | Milestone: 2.4 (future)
Component: General | Version:
Severity: major | Keywords: wp_cron, https
------------------------+---------------------------------------------------
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 at server wp-includes]# diff cron.php cron.php.original
90,91c90
90,91c90
< $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);
96,97c95
< $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.
--
Ticket URL: <http://trac.wordpress.org/ticket/4782>
WordPress Trac <http://trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list