[wp-hackers] Dealing with WP cron's raciness
otto at ottodestruct.com
Thu Sep 19 00:27:21 UTC 2013
On Wed, Sep 18, 2013 at 7:07 PM, David Anderson <david at wordshell.net> wrote:
> Hi Otto,
> Thanks... I was aware of that; the reason I was hitting wp-cron.php directly
> in the tests I mentioned in my early mail was for two reasons: 1) On my
> reading of the code, wp-cron.php tries to apply the same lock (the section
> beginning with the comment "// Use global $doing_wp_cron lock otherwise use
> the GET lock. If no lock, trying grabbing a new lock."). 2) In my tests,
> going indirectly (hitting the site's home page) had the same effect - i.e.
> the action would still consistently run multiple times due to raciness. It
> was just slightly less racy, but I surmised that that was due to a
> side-effect of timing due to the extra HTTP round-trip, rather than due to
> any extra locking taking place (which I surmised because of 1) - I can't see
> any extra locking take place - only a difference as to the timing of *when*
> the locking takes place).
Well, like I said, it's not perfect, but it's still going to be
slightly better as to the timing.
Hitting it directly means that the lock logic is running inside the
hit to wp-cron.php. So if you have multiple instances running
concurrently, then they can both get the same "lock" because of timing
differences between the check and the setting of the lock.
Running it normally means that the lock is grabbed before wp-cron.php
is ever called, in the wp-includes/cron.php file. Now, if you have two
hits in the same second, or hits on multiple servers and the like,
then you can still get the race condition to occur and have the main
cron.php script call the wp-cron.php script twice with the same
values, but this is better for the most part... for a given definition
of "better". :)
If you're expecting more than 1 hit per second on a normal basis, and
it's a problem for your particular setup, then you'd probably be
better served setting DISABLE_WP_CRON and creating a real cron job to
call it every so often instead. It doesn't even have to be a wget to
the URL, you can run it with a direct "php wp-cron.php" command just
fine, for non-multisite instances.
More information about the wp-hackers