Commit d6b3abc8 authored by Erick Hitter's avatar Erick Hitter Committed by GitHub
Browse files

Merge pull request #118 from Automattic/fix/117-deadlock

Catch callback exceptions to avoid deadlock
parents 69a43bef 06a4f200
# Cron Control
Cron Control
============
Execute WordPress cron events in parallel, using a custom post type for event storage.
Using REST API endpoints (requires WordPress 4.4+), an event queue is produced and events are triggered.
## PHP Compatibility
Cron Control requires PHP 7 or greater to be able to catch fatal errors triggered by event callbacks. While the plugin may work with previous versions of PHP, internal locks may become deadlocked if callbacks fail.
## Event Concurrency
In some circumstances, multiple events with the same action can safely run in parallel. This is usually not the case, largely due to Core's alloptions, but sometimes an event is written in a way that we can support concurrent executions.
......
......@@ -268,17 +268,29 @@ class Events extends Singleton {
$this->update_event_record( $event );
// Run the event
do_action_ref_array( $event->action, $event->args );
try {
do_action_ref_array( $event->action, $event->args );
} catch ( \Throwable $t ) {
$return = array(
'success' => false,
'message' => sprintf( __( 'Callback for job with action `%1$s` and arguments `%2$s` raised a Throwable - %3$s in %4$s on line %5$d.', 'automattic-cron-control' ), $event->action, maybe_serialize( $event->args ), $t->getMessage(), $t->getFile(), $t->getLine() ),
);
}
// Free process for the next event, unless it wasn't set to begin with
if ( ! $force ) {
$this->do_lock_cleanup( $event );
}
return array(
'success' => true,
'message' => sprintf( __( 'Job with action `%1$s` and arguments `%2$s` executed.', 'automattic-cron-control' ), $event->action, maybe_serialize( $event->args ) ),
);
// Callback didn't trigger an exception, indicating it succeeded
if ( ! isset( $return ) ) {
$return = array(
'success' => true,
'message' => sprintf( __( 'Job with action `%1$s` and arguments `%2$s` executed.', 'automattic-cron-control' ), $event->action, maybe_serialize( $event->args ) ),
);
}
return $return;
}
/**
......
......@@ -31,7 +31,7 @@ class Lock extends \WP_CLI_Command {
\WP_CLI::error( sprintf( __( 'Specify an action', 'automattic-cron-control' ) ) );
}
$lock_name = \Automattic\WP\Cron_Control\Events::instance()->get_lock_key_for_event_action( array( 'action' => $args[0], ) );
$lock_name = \Automattic\WP\Cron_Control\Events::instance()->get_lock_key_for_event_action( (object) array( 'action' => $args[0], ) );
$lock_limit = 1;
$lock_description = __( "This lock prevents concurrent executions of events with the same action, regardless of the action's arguments.", 'automattic-cron-control' );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment