[wp-hackers] Dealing with WP cron's raciness
Dion Hulse (dd32)
wordpress at dd32.id.au
Fri Sep 20 13:12:29 UTC 2013
On 20 September 2013 22:46, David Anderson <david at wordshell.net> wrote:
> Dion Hulse (dd32) wrote:
>> I just wanted to point out, that doing this bypasses the major component
>> WP Cron which attempts to allow things to only run once.. doing so
>> almost be guaranteed to have duplicate events fired.
>> When WordPress fires off the cron, it creates a locking transient (which
>> should be pretty reliable when using an external object cache, not
>> but still pretty good, when not) which is based on microtime(true) which
>> includes microseconds: 1379596515.**2753798961639404296875
>> The request is then made via
>> wp-cron.php?doing_wp_cron=**1379596515.**2753798961639404296875. If the
>> GET arg
>> doesn't match exactly what's in the transient, that request doesn't
>> any operations.
> Hi Dion,
> Thanks for the feedback... I mentioned before a couple of things:
> 1) My motivation is to torture-test the worst-case scenarios, because they
> are what generate support requests. A significant number (i.e. significant
> enough to generate a flow of support requests, once you have 5,000 new
> installs a week) of hosting companies disable this mechanism (in part,
> through disabling loopback HTTP connections), and instruct their users to
> call wp-cron.php directly (via a scheduler in their control panel). (I know
> that's "non-optimal". I know about ALTERNATE_WP_CRON - as I say, I'm trying
> to deal with what users are doing and likely to keep on doing, not what
> they ought to do).
Yes, If you take the worst-possible case, and bypass the locking mechanisms
which WordPress has, then you will no doubt have more issues, it's really
as simple as that, and as a plugin developer you have to expect the worst
from a users configuration and program defensively.
WordPress can't work 100% under every condition, and will do it's best
under the conditions presented.
Unfortunately, WordPress only has a default cron timeout of 60 seconds when
you call wp-cron.php directly, so if you have a real cronjob running every
2 minutes, even if the first cron is still running, the 2nd will assume
that the first has timed out due to poor hosting configurations or a PHP
error - both conditions that it has to contend with as many hosts will kill
processes after 45~60 seconds still.
If you're calling wp-cron.php directly, and you want each process to hold
the lock longer, you can define 'WP_CRON_LOCK_TIMEOUT' in wp-config.php to
increase the time (it defaults to 60 as mentioned before).
It should be safe to increase it to 5 minutes (300) with minimal issues for
> 2) I said before to Otto that from my reading of the code in wp-cron.php,
> there's also an attempt to apply the same locking mechanism you describe
> above in there. The only difference is that the loopback HTTP introduces a
> slightly random timing delay, which fortuitously gives the time delay
> needed for the locking mechanism to work - i.e. the effect is a side-effect
> of the method,rather than procured directly by it. Am I reading that wrong?
The loopback request doesn't really cause any benefit due to delays or
anything, the only benefit is that in doing so, it's locking the cron
request for the DURATION of the cronjob through the random url value, where
as when you call wp-cron.php directly, you're only locking it for
I don't say this lightly, I'm just trying to explain how the current system
works, if you have some ideas on how to improve the experience for users,
while retaining compatibility with shitty hosts and bad PHP configurations
(and even worse plugins) then I'm all ears, and would love to see you
submit a trac ticket with a patch or suggestions.
More information about the wp-hackers