Make WordPress Core

Opened 6 years ago

Last modified 14 months ago

#13158 new defect (bug)

Cron : some events may not be scheduled

Reported by: arena Owned by: westi
Milestone: Future Release Priority: high
Severity: major Version: 3.1
Component: Cron API Keywords: needs-patch
Focuses: Cc:


the problem appears when two different events are scheduled at the same time

what happens in code is :

1st event : _get_cron_array();
2nd event : _get_cron_array();

1st event : _set_cron_array( $crons );
2nd event : _set_cron_array( $crons );

1st event is lost.

Change History (15)

#1 @mdawaffe
6 years ago

The root problem is that we store the cron data in an array. A naive get, process, set algorithm will always be prone to race conditions.

We can rework those scheduling functions to move as much of the processing before the get so that there's less time between the get and the set, but that won't solve the problem. Most of the bottleneck is probably in the db write, so reducing the time spent in PHP between get and set probably won't help that much.

We could try putting in some locking (in the application layer) and maybe making a queue of stuff that needs to be added (one per row or we're back to where we started... transients?), but I don't think that will guarantee we prevent the race condition. More complicated and easy to just move the race condition from one area to another.

#2 @ryan
6 years ago

  • Milestone changed from 3.0 to Future Release

#3 @arena
6 years ago

  • Milestone changed from Future Release to 3.0

Best would be to convert cron arrays in a set of rows in options table with same meta_key, meta_value containing timestamp, hook, args

#4 @nacin
6 years ago

The options table doesn't have "meta_key" or "meta_value." Option names must be unique.

We will not do any sort of restructuring here this close to release. Moving back to future.

#5 @nacin
6 years ago

  • Milestone changed from 3.0 to Future Release

#6 @arena
5 years ago

  • Version changed from 3.0 to 3.1

#7 @mintindeed
5 years ago

  • Cc gabriel.koen@… added

Why does it have to stay in the wp_options table? Looking at implementations of a cron or job queue (I'm thinking Magento at the moment, but there are other examples), the implementations that are built for concurrency and volume use a separate table for maintaining the queue. That seems like it would be appropriate here as well.

#8 @mintindeed
5 years ago

It looks like #15148 would fix this by extension, allowing those to whom concurrency is an issue to implement their own cron storage and queueing options, a la HyperDB.

#9 @vickybiswas
5 years ago

A Method I used successfully for this specific case maybe helps here

 * Clean Cron from cache so that fresh is fetched
 * @since 2011-05-18 Vicky Biswas
add_action( 'pre_update_option_cron', 'mmc_pre_update_option_cron',10 );
function mmc_pre_update_option_cron() {
	$alloptions = wp_load_alloptions();
    	if ( isset( $alloptions['cron'] ) ) {
		unset ($alloptions['cron']);
		wp_cache_set( 'alloptions', $alloptions, 'options' );
    	} else
        	wp_cache_delete( 'cron', 'options' );
    	return false;

#10 @agupta_pmc
5 years ago

  • Cc agupta_pmc added

#11 @obenland
3 years ago

FWIW, I wouldn't consider this a bug, but rather a misusage of the API. _get_cron_array() and _set_cron_array() are both private functions, which shouldn't be called directly anyway.

The phenomenon will not occur when one of the wp_schedule_*_event() wrappers are used.

#12 @arena
3 years ago

@obenland, as long as the api is not using some kind of semaphore this can occur !

#13 follow-up: @obenland
3 years ago

I agree! :)

But it would be a blunt disregard of the API and the purpose of these functions, which shouldn't be supported by making it work, IMO.

#14 in reply to: ↑ 13 @arena
3 years ago

Replying to obenland:

I agree! :)

so reconsider your first message as 'this is a misusage of the API'.
This is a bug !

#15 @wonderboymusic
14 months ago

  • Keywords needs-patch added
Note: See TracTickets for help on using tickets.