Make WordPress Core

Opened 11 years ago

Closed 3 years ago

#24160 closed defect (bug) (fixed)

ALTERNATE_WP_CRON runs wp_cron() too early

Reported by: r-a-y's profile r-a-y Owned by: peterwilsoncc's profile peterwilsoncc
Milestone: 5.7 Priority: normal
Severity: normal Version: 3.4
Component: Cron API Keywords: has-patch early commit
Focuses: Cc:

Description (last modified by SergeyBiryukov)

See #19818 for full details.

Then, read my comment in that ticket. Was advised to create a new ticket.

We need to run 'wp_cron' later than the default priority of 10 to allow plugins that run on this hook to properly initialize.

In the patch, I've bumped the priority to 99. Let me know what you think.

Attachments (1)

24160.01.patch (522 bytes) - added by r-a-y 11 years ago.

Download all attachments as: .zip

Change History (24)

@r-a-y
11 years ago

#1 @SergeyBiryukov
11 years ago

  • Milestone changed from Awaiting Review to 3.6

#2 @SergeyBiryukov
11 years ago

  • Summary changed from ALTERNATE_WP_CRON runs 'init' too late to ALTERNATE_WP_CRON runs 'init' too early

#3 @SergeyBiryukov
11 years ago

  • Summary changed from ALTERNATE_WP_CRON runs 'init' too early to ALTERNATE_WP_CRON runs wp_cron() too early

#4 @r-a-y
11 years ago

Thanks for correcting the ticket title, Sergey!

And thanks for the feedback from the previous ticket.

#5 @prettyboymp
11 years ago

To match where it runs with a normal cron, the hook should probably be changed to 'wp_loaded'.

#6 @ryan
11 years ago

  • Milestone changed from 3.6 to Future Release

#7 @SergeyBiryukov
10 years ago

  • Description modified (diff)
  • Keywords 4.1-early added

#8 @chriscct7
8 years ago

  • Keywords 4.1-early removed

#9 @chriscct7
8 years ago

  • Keywords early added

#11 @peterwilsoncc
5 years ago

  • Milestone set to Future Release
  • Status changed from new to reopened

This is worth some investigation so I'm reopening this and putting it down for a future release. The Cron component has a bit of a backlog, so I won't give a timeframe for now as it would set a false expectation.

#12 @peterwilsoncc
5 years ago

#37542 was marked as a duplicate.

#13 @peterwilsoncc
5 years ago

From #37542:

This can be an issue for sites registering custom taxonomies. Taxos can not be registered prior to the init hook but using the default priority causes the taxo to be registered after the cron hook fires when using alternative cron.

This ticket was mentioned in Slack in #core by peterwilsoncc. View the logs.


4 years ago

#15 @peterwilsoncc
3 years ago

  • Keywords needs-refresh added
  • Milestone changed from Future Release to 5.7
  • Owner set to peterwilsoncc
  • Status changed from reopened to assigned

Moving this on to the 5.7 milestone for an early look.

  • I understand this will have a side-effect of fixing #20537 too
  • It's a backward compatibility break to simply move the action from 10 to a higher number. It's possible to maintain it by using wp_cron to register an action to run later on init. Possible but ugly.

#16 @johnbillion
3 years ago

I'm happy to help out with any of these cron tickets Peter, just shout.

#17 @peterwilsoncc
3 years ago

Doing some research to determine backward compatibility issues.

https://wpdirectory.net/search/01ESJ720E4PB7VBTX7YMYX9JTB

  • ten plugins run remove_action( 'init', 'wp_cron' )
  • the three most popular have 300K+, 40K+, and 20K+ installs

I do like @prettyboymp's suggestion above of moving the wp_loaded function to match the execution point in which alternative cron runs to the standard wp-cron. It would probably need to run late on that too (ie, priority 20 or higher).

---

@johnbillion I think it's safest to go with some ugly code to maintain backward compatibility. What are your thoughts on the following?

wp_cron() renamed to _wp_cron(), wp_cron_loaded() or similar.

wp_cron() continues to run on init, 10 and then looks something like this:

function wp_cron() {
  if ( did_action( 'wp_loaded' ) {
    return _wp_cron();
  }

  add_action( 'wp_loaded', '_wp_cron', 20 );
}

This ticket was mentioned in Slack in #core by lukecarbis. View the logs.


3 years ago

This ticket was mentioned in Slack in #core by hellofromtonya. View the logs.


3 years ago

This ticket was mentioned in PR #842 on WordPress/wordpress-develop by peterwilsoncc.


3 years ago
#20

  • Keywords needs-refresh removed

This ticket was mentioned in Slack in #core by metalandcoffee. View the logs.


3 years ago

#22 @johnbillion
3 years ago

For anyone like me who is trying to wrap their head around what exactly the problem is:

  • When wp-cron.php is accessed with a direct POST request, either as a result of spawn_cron() or as a result of a real server cron job requesting it, wp-load.php is included and then any pending cron events are iterated and run. This means actions such as init and wp_loaded have finished executing by the point where the cron events are run.
  • With ALTERNATE_WP_CRON in use, the wp_cron() function that's hooked into init does an include_once( 'wp-cron.php' ) which then iterates and runs pending cron events after flushing a redirect header to the client.

This means with ALTERNATE_WP_CRON in use, cron events run within the init hook on priority 10. Without it in use, they run after the wp_loaded action has fired.

To bring these two situations closer, the wp_cron() function should be hooked into wp_loaded with a late priority, as per Peter's comment and PR above.

Last edited 3 years ago by johnbillion (previous) (diff)

#23 @johnbillion
3 years ago

  • Keywords commit added

#24 @peterwilsoncc
3 years ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 50135:

Cron API: Run alternative wp-cron later, do not run on archived blogs.

Runs cron jobs later on sites using alternative cron, ie the ALTERNATE_WP_CRON constant is true, to more closely match when standard cron jobs are run. Jobs now run on the wp_loaded hook at priority 20. Prior to this change they would run on the init hook. This ensures custom post types and taxonomies are registered prior to the jobs running.

This change also prevents alternative wp-cron from running on archived or suspended multisite blogs as these are shut down prior to the wp_loaded hook from running.

Moves the existing functionality of wp_cron() in to a new private function _wp_cron().

Props flixos90, jeremyfelt, johnbillion, jrf, kurtpayne, nacin, peterwilsoncc, prettyboymp, r-a-y, ryan, stevenkword, swissspidy.
Fixes #20537, #24160.

Note: See TracTickets for help on using tickets.