WordPress.org

Make WordPress Core

Opened 7 years ago

Closed 6 years ago

Last modified 6 years ago

#28213 closed defect (bug) (fixed)

wp_schedule_single_event() prevents scheduling a future event when it should not

Reported by: tellyworth Owned by: wonderboymusic
Milestone: 4.1 Priority: normal
Severity: normal Version:
Component: Cron API Keywords: has-patch
Focuses: Cc:

Description

[9181] added some defensive code to wp_schedule_single_event() suggested in #6966, to stop scheduling duplicate events in the event of a flood.

That patch did solve the intended problem, but also introduced some unintended behaviour. If an event is currently executing, or is past due but hasn't completed for some reason, it will refuse to schedule a similar event at any future time - even if you attempt to schedule something weeks ahead.

This turned up when testing the Akismet plugin: in the event that servers are unreachable, the cron_recheck() hook attempts to re-schedule itself for 6 hours in the future. But wp_schedule_single_event() rejects it because there is already a similar event scheduled a few seconds in the past (itself).

That wasn't the intent of the original fix, and I think it should be considered a bug. I'd suggest that wp_schedule_single_event() should only reject an event as a duplicate if there is already a similar event scheduled within 10 minutes of the given timestamp.

While testing this I discovered there's a bug in the associated unit test, Tests_Cron::test_not_duplicate_event(). It schedules two future events and checks that they are both there. wp_next_scheduled() returns the wrong event (it returns the later event, not the next), but the test as written incorrectly accepts this as expected behaviour.

Attachments (1)

wp_schedule_single_event-r28372.patch (2.1 KB) - added by tellyworth 7 years ago.

Download all attachments as: .zip

Change History (6)

#1 @tellyworth
7 years ago

The patch fixes the bug, and the unit test, and adds a second test to cover the reverse order.

Thanks @cfinke for suggesting the fix.

#2 @lkraav
7 years ago

I wonder if this is what I'm running into. I am running a cron job every minute that does a network operation. This network operation has a percentage chance of timing out or not completing by the time next cron event next minute is in theory scheduled to run.

Result is that my cronjob arbitrarily simply disappears from the list. I can still see my custom 1 minute schedule in Cron Debug Bar, so I know my uber-simple cron plugin is setting things up right. But unless I re-cycle plugin activation, my cron job will never run again.

Uber-simple plugin for reference:

register_activation_hook( __FILE__, array( "MyClass", "cron_setup" ) );
register_deactivation_hook( __FILE__, array( "MyClass", "cron_remove" ) );

MyClass::on_load();

class MyClass {
    static function on_load() {
        add_filter( "cron_schedules", array( __CLASS__, "ny_minute" ) );
        add_action( "myclass_resend_failed", array( __CLASS__, "resend_failed" ) );
    }

    static function cron_setup() {
        wp_schedule_event( time(), "minutes_1", "myclass_resend_failed" );
    }

    static function cron_remove() {
        wp_clear_scheduled_hook( "myclass_resend_failed" );
    }

    static function ny_minute( $schedules ) {
        $schedules[ "minutes_1" ] = array( "interval" => 60, "display" => "Once every NY minute" )

        return $schedules;
    }

    static function resend_failed() {
        # do magic, but occasionally timeouting network stuff here
    }
Last edited 7 years ago by lkraav (previous) (diff)

#3 @wonderboymusic
6 years ago

  • Keywords has-patch added
  • Milestone changed from Awaiting Review to 4.1

#4 @wonderboymusic
6 years ago

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

In 29939:

wp_schedule_single_event() should not prevent scheduling a future duplicate event. It should only reject an event as a duplicate if there is already a similar event scheduled within 10 minutes of the given timestamp.

Adds unit tests, fixes existing cron test.

Props tellyworth.

See [9181], #6966.
Fixes #28213.

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


6 years ago

Note: See TracTickets for help on using tickets.