diff --git a/includes/common.inc b/includes/common.inc index 1ef681f121a9afdbed0b40a206cd72792bb6a08e..f54f29a7c39faf62f1f1ece5e0c601f4009d2952 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 9b6178804c9087b7d5144e45a23d6f7d48fc0d87..c400eaed11423b857b50fed0c31160f7c17e416c 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 0000000000000000000000000000000000000000..ce1a6326fb330068c919cb1e614f028be4aab01a --- /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 = 7.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 0000000000000000000000000000000000000000..94a2b2c43821ae8e8f41ff6a3a6a81fbc984868e --- /dev/null +++ b/modules/simpletest/tests/common_test_cron_helper.module @@ -0,0 +1,17 @@ +<?php +/** + * @file + * Helper module for the testCronExceptions in addition to common_test module. + */ + +/** + * Implements hook_cron(). + * + * common_test_cron() throws an exception, but the execution should reach this + * function as well. + * + * @see common_test_cron() + */ +function common_test_cron_helper_cron() { + variable_set('common_test_cron', 'success'); +} diff --git a/modules/system/system.test b/modules/system/system.test index 181ddeafd29ed12f7f8ef7fa511ff542155b4d03..1ce8e6b7e0ed106cc7582a32d8f4e14f64f5357b 100644 --- a/modules/system/system.test +++ b/modules/system/system.test @@ -695,6 +695,10 @@ class CronRunTestCase extends DrupalWebTestCase { ); } + function setUp() { + parent::setUp(array('common_test', 'common_test_cron_helper')); + } + /** * Test cron runs. */ @@ -799,6 +803,19 @@ class CronRunTestCase extends DrupalWebTestCase { $this->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 {