Make WordPress Core

Opened 12 years ago

Closed 12 years ago

#19700 closed defect (bug) (fixed)

Cron locking still not fixed in 3.3

Reported by: archon810's profile archon810 Owned by: ryan's profile ryan
Milestone: 3.4 Priority: normal
Severity: major Version: 3.3
Component: Cron API Keywords:
Focuses: Cc:


Re-opening the issue due to #17462 not fixing the problem once and for all.

This is what I posted as the last comment there before getting instructed to start a new ticket:

I don't think the bug is fixed. After posting a new post, I experienced a load spike (2 -> 20) and found this in the server status:

Additionally, today I stuck an error_log() statement into something that gets scheduled like this:

function my_publish_post($new_status, $old_status, $post) {
  wp_schedule_single_event(time()+150, 'my_feedburner_ping');
add_action( 'my_feedburner_ping', 'my_feedburner_ping' );
function my_feedburner_ping() {
  error_log(print_r(wp_remote_get("" . urlencode(home_url())), 1));

The log shows 2 events, on the exact same second. [Fri Dec 30 10:02:26 2011] [error] and so on. The HTTP headers are different, so I know 2 separate requests went out. And this is on a relatively slow eve of New Year's eve and a load of 2 on a quad-core machine. If the server was more loaded, we could probably see 5-10 of these.

The current solution doesn't seem to be truly atomic and multi-thread friendly.

Attachments (2)

19700.diff (1.4 KB) - added by ryan 12 years ago.
microtime( true )
19700.2.diff (1.9 KB) - added by ryan 12 years ago.
Preserve precision

Download all attachments as: .zip

Change History (9)

#1 @archon810
12 years ago

  • Cc admin@… added

#2 @johnbillion
12 years ago

  • Cc johnbillion@… added

#3 @dd32
12 years ago

It looks like we're still using time() for the unique cron lock? Perhaps changing this to microtime(true) (to get a float with milliseconds) or some other unique hash will help limit the occurrences of this happening. I'm thinking perhaps a Hash of some environmental variables unique to each user..

#4 @archon810
12 years ago

Finer than a second resolution is definitely needed. Another option would be to look into mutexes using something like flock or semaphores (, but really, what I found working great before is microsecond time stored in a database, then doing an update on that time with a WHERE clause that takes the microsecond value from the SELECT and seeing how many rows are updated. If 1, then WHERE matched and you were the first one to grab the row. If 0, some other process already updated, and you shouldn't do anything. I'm sure the WP team can figure out the best solution.

#5 @ryan
12 years ago

  • Milestone changed from Awaiting Review to 3.4

Using microtime and perhaps adding something unique to distinguish requests is on the todo for 3.4. Let's track that work with this ticket. Patches welcome.

A mutex gets messy when there is more than one server involved. I'd rather invest effort in allowing WP to use outside jobs systems. see #15148

12 years ago

microtime( true )

12 years ago

Preserve precision

#6 @ryan
12 years ago

That patch results in a doing_cron transient that looks like: 1326050455.4191329479217529296875. The microtime float is cast to a string with sprintf() to avoid loss of resolution when passing it to db/cache and wp-cron.php. The lock tests compare doing_cron and doing_wp_cron as strings. We could add a few random digits to the end to make each request even more unique.

#7 @ryan
12 years ago

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

In [19722]:

Use microtime() for cron locks. fixes #19700

Note: See TracTickets for help on using tickets.