Commit 17f3807f authored by Dries's avatar Dries

- Patch #566494 by Dave Reid, chx, JoshuaRogers, David_Rothstein, Gábor...

- Patch #566494 by Dave Reid, chx, JoshuaRogers, David_Rothstein, Gábor Hojtsy, moshe weitzman, Rob Loach, TheRec, catch: fixed cron doing a full bootstrap on every page request (including cached ones).
parent 06daeb7d
......@@ -237,7 +237,7 @@ INSTALLATION
Note, however, that cron tasks will only be executed when there are site
visitors. You can enable the built-in cron feature at:
Administer > Configuration and modules > Development > Maintenance mode
Administer > Configuration > System > Site information
Advanced users may want to ensure that cron tasks are executed periodically.
To do this, visit the page "cron.php", which executes maintenance tasks on
......
......@@ -4528,6 +4528,8 @@ function _drupal_bootstrap_full() {
fix_gpc_magic();
// Load all enabled modules
module_load_all();
// Register automated cron run handler.
register_shutdown_function('system_run_automated_cron');
// Make sure all stream wrappers are registered.
file_get_stream_wrappers();
if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'simpletest') !== FALSE) {
......
......@@ -1560,7 +1560,6 @@ function system_site_information_settings() {
);
$form['#validate'][] = 'system_site_information_settings_validate';
$form['#submit'][] = 'system_site_information_settings_submit';
return system_settings_form($form, FALSE);
}
......@@ -1581,18 +1580,6 @@ function system_site_information_settings_validate($form, &$form_state) {
}
}
/**
* Form submit handler for the site-information form.
*/
function system_site_information_settings_submit($form, &$form_state) {
// Clear caches when the cron threshold is changed to ensure that the cron
// image is not contained in cached pages.
$cron_threshold = variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD);
if ($cron_threshold != $form_state['input']['cron_safe_threshold']) {
cache_clear_all();
}
}
/**
* Form builder; Configure error reporting settings.
*
......
......@@ -527,13 +527,6 @@ function system_menu() {
'type' => MENU_CALLBACK,
'file' => 'system.admin.inc',
);
$items['system/run-cron-check'] = array(
'title' => 'Execute cron',
'page callback' => 'system_run_cron_check',
'access callback' => 'system_run_cron_check_access',
'type' => MENU_CALLBACK,
'file' => 'system.admin.inc',
);
$items['admin'] = array(
'title' => 'Administer',
'access arguments' => array('access administration pages'),
......@@ -3083,32 +3076,6 @@ function system_retrieve_file($url, $destination = NULL, $overwrite = TRUE) {
return $local;
}
/**
* Implements hook_page_build().
*/
function system_page_build(&$page) {
// Automatic cron runs.
$cron_threshold = variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD);
if ($cron_threshold) {
$page['page_bottom']['run_cron'] = array(
// Trigger cron run via AJAX.
'#attached' => array(
'js' => array(
drupal_get_path('module', 'system') . '/system.cron.js' => array('weight' => JS_DEFAULT - 5),
array(
'data' => array(
// Add the timestamp for the next automatic cron run.
'cronCheck' => variable_get('cron_last', 0) + $cron_threshold,
),
'type' => 'setting',
),
),
),
);
}
}
/**
* Implements hook_page_alter().
*/
......@@ -3125,65 +3092,15 @@ function system_page_alter(&$page) {
}
/**
* Menu callback; executes cron via an AJAX callback.
*
* This callback runs cron in a separate HTTP request to prevent "mysterious"
* slow-downs of regular HTTP requests. It is invoked via an AJAX request and
* does not process the returned output.
*
* @see system_page_alter()
* @see system_run_cron_check_access()
* Run the automated cron if enabled.
*/
function system_run_cron_check() {
$cron_run = FALSE;
$cron_threshold = variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD);
// Cron threshold semaphore is used to avoid errors every time the image
// callback is displayed when a previous cron is still running.
$threshold_semaphore = variable_get('cron_threshold_semaphore', FALSE);
if ($threshold_semaphore) {
if (REQUEST_TIME - $threshold_semaphore > 3600) {
// Either cron has been running for more than an hour or the semaphore
// was not reset due to a database error.
watchdog('cron', 'Cron has been running for more than an hour and is most likely stuck.', array(), WATCHDOG_ERROR);
// Release the cron threshold semaphore.
variable_del('cron_threshold_semaphore');
}
}
else {
function system_run_automated_cron() {
if (($threshold = variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD)) > 0) {
$cron_last = variable_get('cron_last', NULL);
// Run cron automatically if it has never run or threshold was crossed.
if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $cron_threshold)) {
// Lock cron threshold semaphore.
variable_set('cron_threshold_semaphore', REQUEST_TIME);
$cron_run = drupal_cron_run();
// Release the cron threshold semaphore.
variable_del('cron_threshold_semaphore');
if (!isset($cron_last) || (REQUEST_TIME - $cron_last > $threshold)) {
drupal_cron_run();
}
}
// Add an expires header with the time of the next cron run.
$cron_last = variable_get('cron_last', NULL);
drupal_add_http_header('Expires', gmdate(DATE_RFC1123, $cron_last + $cron_threshold));
drupal_json_output(array('cron_run' => $cron_run));
drupal_page_footer();
}
/**
* Checks if the feature to automatically run cron is enabled.
*
* Also used as a menu access callback for this feature.
*
* @return
* TRUE if cron threshold is enabled, FALSE otherwise.
*
* @see system_run_cron_check()
* @see system_page_alter()
*/
function system_run_cron_check_access() {
return variable_get('cron_safe_threshold', DRUPAL_CRON_DEFAULT_THRESHOLD) > 0;
}
/**
......
......@@ -422,7 +422,7 @@ class CronRunTestCase extends DrupalWebTestCase {
}
/**
* Ensure that the automatic cron run callback is working.
* Ensure that the automatic cron run feature is working.
*
* In these tests we do not use REQUEST_TIME to track start time, because we
* need the exact time when cron is triggered.
......@@ -435,19 +435,13 @@ class CronRunTestCase extends DrupalWebTestCase {
variable_set('cron_last', $cron_last);
variable_set('cron_safe_threshold', $cron_safe_threshold);
$this->drupalGet('');
$this->assertRaw('"cronCheck":' . ($cron_last + $cron_safe_threshold));
$this->drupalGet('system/run-cron-check');
$this->assertExpiresHeader($cron_last + $cron_safe_threshold);
$this->assertTrue($cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is not passed.'));
// Test if cron runs when the cron threshold was passed.
$cron_last = time() - 200;
variable_set('cron_last', $cron_last);
$this->drupalGet('');
$this->assertRaw('"cronCheck":' . ($cron_last + $cron_safe_threshold));
sleep(1);
$this->drupalGet('system/run-cron-check');
$this->assertExpiresHeader(variable_get('cron_last', NULL) + $cron_safe_threshold);
$this->assertTrue($cron_last < variable_get('cron_last', NULL), t('Cron runs when the cron threshold is passed.'));
// Disable the cron threshold through the interface.
......@@ -461,24 +455,9 @@ class CronRunTestCase extends DrupalWebTestCase {
$cron_last = time() - 200;
variable_set('cron_last', $cron_last);
$this->drupalGet('');
$this->assertNoRaw('cronCheck');
$this->drupalGet('system/run-cron-check');
$this->assertResponse(403);
$this->assertTrue($cron_last == variable_get('cron_last', NULL), t('Cron does not run when the cron threshold is disabled.'));
}
/**
* Assert that the Expires header is a specific timestamp.
*
* @param $timestamp
* The timestamp value to match against the header.
*/
private function assertExpiresHeader($timestamp) {
$expires = $this->drupalGetHeader('Expires');
$expires = strtotime($expires);
$this->assertEqual($expires, $timestamp, t('Expires header expected @expected got @actual.', array('@expected' => $timestamp, '@actual' => $expires)));
}
/**
* Ensure that temporary files are removed.
*
......
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