diff --git a/includes/common.inc b/includes/common.inc index 1e287f8..88dc2fb 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -5041,7 +5041,15 @@ function drupal_cron_run() { drupal_register_shutdown_function('drupal_cron_cleanup'); // Iterate through the modules calling their cron handlers (if any): - module_invoke_all('cron'); + foreach (module_implements('cron') as $module) { + // Do not let an exception thrown by one module disturb another. + try { + module_invoke($module, 'cron'); + } + catch (Exception $e) { + watchdog_exception('cron', $e); + } + } // Record cron time variable_set('cron_last', REQUEST_TIME); diff --git a/modules/simpletest/tests/common_test.module b/modules/simpletest/tests/common_test.module index 9b61788..c400eae 100644 --- a/modules/simpletest/tests/common_test.module +++ b/modules/simpletest/tests/common_test.module @@ -225,3 +225,16 @@ function common_test_js_and_css_querystring() { drupal_add_css('/' . drupal_get_path('module', 'node') . '/node-fake.css?arg1=value1&arg2=value2'); return ''; } + +/** + * Implements hook_cron(). + * + * System module should handle if a module does not catch an exception and keep + * cron going. + * + * @see common_test_cron_helper() + * + */ +function common_test_cron() { + throw new Exception(t('Uncaught exception')); +} diff --git a/modules/simpletest/tests/common_test_cron_helper.info b/modules/simpletest/tests/common_test_cron_helper.info new file mode 100644 index 0000000..ff7b17a --- /dev/null +++ b/modules/simpletest/tests/common_test_cron_helper.info @@ -0,0 +1,6 @@ +name = "Common Test Cron Helper" +description = "Helper module for CronRunTestCase::testCronExceptions()." +package = Testing +version = VERSION +core = 8.x +hidden = TRUE diff --git a/modules/simpletest/tests/common_test_cron_helper.module b/modules/simpletest/tests/common_test_cron_helper.module new file mode 100644 index 0000000..94a2b2c --- /dev/null +++ b/modules/simpletest/tests/common_test_cron_helper.module @@ -0,0 +1,17 @@ +assertTrue(file_exists($perm_old->uri), t('Old permanent file was correctly ignored.')); $this->assertTrue(file_exists($perm_new->uri), t('New permanent file was correctly ignored.')); } + + /** + * Make sure exceptions thrown on hook_cron() don't affect other modules. + */ + function testCronExceptions() { + variable_del('common_test_cron'); + // The common_test module throws an exception. If it isn't caught, the tests + // won't finish successfully. + // The common_test_cron_helper module sets the 'common_test_cron' variable. + $this->cronRun(); + $result = variable_get('common_test_cron'); + $this->assertEqual($result, 'success', t('Cron correctly handles exceptions thrown during hook_cron() invocations.')); + } } class AdminMetaTagTestCase extends DrupalWebTestCase {