[wp-trac] [WordPress Trac] #57924: Cron fires twice (was: Cron Goes Missing. _set_cron_array called with incorrect number of crons)

WordPress Trac noreply at wordpress.org
Thu Mar 16 22:32:13 UTC 2023


#57924: Cron fires twice
--------------------------+------------------------------
 Reporter:  j3gaming      |       Owner:  j3gaming
     Type:  defect (bug)  |      Status:  assigned
 Priority:  normal        |   Milestone:  Awaiting Review
Component:  Cron API      |     Version:  6.1.1
 Severity:  normal        |  Resolution:
 Keywords:                |     Focuses:
--------------------------+------------------------------

Comment (by j3gaming):

 At this point I'm just using the ticket as a chronicle of my journey until
 I give up.
 Hope the spam is fine!

 I set some more logging. **wp-cron.php** this time:


 {{{
 /*
  * The cron lock (a unix timestamp set when the cron was spawned),
  * must match $doing_wp_cron (the "key").
  */
 if ( $doing_cron_transient !== $doing_wp_cron ) {
         return;
 }

 error_log(" START --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- ");
 error_log("[wp-cron.php] Jobs ready: " . count($crons) . ", with UNIX key:
 " . var_export($doing_cron_transient, true));

 foreach ( $crons as $timestamp => $cronhooks ) {

 ...
 // ... all the usual normal WP code ...
 ...

 if ( _get_cron_lock() === $doing_wp_cron ) {
         delete_transient( 'doing_cron' );
 }

 error_log(" --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- END");
 die();
 }}}

 You would expect to NEVER get 2 "starts" in a row right?
 It's possible. Notice the different $doing_cron_transient outputs? The
 microtime(true) is slightly different. At the end of the log, I do get
 double the outputs from my code inside the cron.


 {{{
 [16-Mar-2023 22:05:01 UTC]  START --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- ---
 [16-Mar-2023 22:05:01 UTC] [wp-cron.php] Jobs ready: 1, with UNIX key:
 '1679004301.2089200019836425781250'
 [16-Mar-2023 22:05:01 UTC] wp_schedule_event(1679004332, 'minutely',
 'crontrol_cron_job', array (
   'code' => 'require_once(\'wp-content/cron/email_send.php\');',
   'name' => 'Send Emails',
 ) , .... )
 [16-Mar-2023 22:05:01 UTC]  START --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- ---
 [16-Mar-2023 22:05:01 UTC] [wp-cron.php] Jobs ready: 1, with UNIX key:
 '1679004301.2094271183013916015625'
 [16-Mar-2023 22:05:01 UTC] wp_schedule_event(1679004332, 'minutely',
 'crontrol_cron_job', array (
   'code' => 'require_once(\'wp-content/cron/email_send.php\');',
   'name' => 'Send Emails',
 ) , .... )
 [16-Mar-2023 22:05:01 UTC] wp_unschedule_event(1679004272,
 'crontrol_cron_job', array (
   'code' => 'require_once(\'wp-content/cron/email_send.php\');',
   'name' => 'Send Emails',
 ) , .... )
 [16-Mar-2023 22:05:01 UTC] Cron reschedule event error for hook:
 crontrol_cron_job, Error code: could_not_set, Error message: The cron
 event list could not be saved. true false, Data:
 {"schedule":"minutely","args":{"code":"require_once('wp-
 content\/cron\/email_send.php');","name":"Send Emails"},"interval":"60"}
 [16-Mar-2023 22:05:01 UTC] wp_unschedule_event(1679004272,
 'crontrol_cron_job', array (
   'code' => 'require_once(\'wp-content/cron/email_send.php\');',
   'name' => 'Send Emails',
 ) , .... )
 [16-Mar-2023 22:05:01 UTC] Cron unschedule event error for hook:
 crontrol_cron_job, Error code: could_not_set, Error message: The cron
 event list could not be saved. true false, Data:
 {"schedule":"minutely","args":{"code":"require_once('wp-
 content\/cron\/email_send.php');","name":"Send Emails"},"interval":"60"}
 [16-Mar-2023 22:05:01 UTC] [1679004301] Started email_send
 [16-Mar-2023 22:05:01 UTC] [1679004301] Started email_send
 [16-Mar-2023 22:05:01 UTC] [1679004301] Ended email_send
 [16-Mar-2023 22:05:01 UTC] [1679004301] Ended email_send
 [16-Mar-2023 22:05:01 UTC]  --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
 --- --- --- --- --- --- --- --- --- --- END

 }}}



 When The cron gets past the lock, firing twice I can trigger
 could_not_set.

 **Proposed fix: Better locking to ensure it only runs once.**
 Not sure if I can help further. I'm unsure how this would change to ensure
 the lock is properly coded & checked.

 Maybe something like a sleep for 1 second, and re-check the lock? Only the
 first or last to get there gets to execute the cron?

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/57924#comment:13>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list