--- includes/common.inc.1.831	Sat Nov 29 15:23:51 2008
+++ includes/common.inc	Sat Nov 29 17:22:12 2008
@@ -1764,6 +1764,28 @@ function drupal_eval($code) {
 }
 
 /**
+ * Attempt to increase the PHP maximum execution time.
+ *
+ * A wrapper around PHP's set_time_limit(). Checks the current time limit to
+ * make sure we don't accidentally reduce it, and avoids trying to change it
+ * in unfriendly server environments.
+ * Note that a time limit of 0 means unlimited.
+ *
+ * @param $desired_time_limit
+ *   (int) The desired time limit, in seconds.
+ */
+
+function drupal_set_time_limit($desired_time_limit) {
+  // Check if we can change the time limit.
+  $safe_mode = trim(ini_get('safe_mode'));
+  if ((empty($safe_mode) || strtolower($safe_mode) == 'off') && function_exists('set_time_limit')) {
+    if (($desired_time_limit == 0) || (is_numeric($current_time_limit = ini_get('max_execution_time')) && $current_time_limit > 0 && $desired_time_limit > $current_time_limit)) {
+      set_time_limit($desired_time_limit);
+    }
+  }
+}
+
+/**
  * Returns the path to a system item (module, theme, etc.).
  *
  * @param $type
@@ -2848,8 +2870,8 @@ function drupal_cron_run() {
   // Allow execution to continue even if the request gets canceled.
   @ignore_user_abort(TRUE);
 
-  // Increase the maximum execution time.
-  @set_time_limit(240);
+  // Try to increase the maximum execution time.
+  drupal_set_time_limit(240);
 
   // Fetch the cron semaphore
   $semaphore = variable_get('cron_semaphore', FALSE);
--- modules/simpletest/tests/common.test.1.17	Sat Nov 29 15:23:53 2008
+++ modules/simpletest/tests/common.test	Sat Nov 29 17:55:13 2008
@@ -521,3 +521,42 @@ class DrupalErrorHandlerUnitTest extends
     $this->assertText($message, t("Found '%message' in error page.", array('%message' => $message)));
   }
 }
+
+/**
+ * Test increasing PHP's maximum execution time.
+ *
+ * Note that these tests will fail if the server environment is not appropriate,
+ * i.e. if safe_mode is on, or if PHP's set_time_limit() is disabled.
+ *
+ * Also note that drupal_set_time_limit() doesn't do any checking on the validity
+ * of the supplied $desired_time_limit, so we don't test that here.  
+ */
+class CommonTimeLimitTestCase extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => t('Set PHP maximum execution time'),
+      'description' => t("Test increasing the PHP time limit. Requires safe_mode off, and PHP's set_time_limit() not disabled."),
+      'group' => t('System'),
+    );
+  }
+
+  function testSetTimeLimit() {
+    // Check time limit not modified if existing value is invalid.
+    set_time_limit('invalid');
+    drupal_set_time_limit(30);
+    $this->assertEqual(ini_get('max_execution_time'), 'invalid', t('Check time limit not modified if existing value is invalid.'));
+
+    // Check we can't reduce the time limit.
+    set_time_limit(100);
+    drupal_set_time_limit(99);
+    $this->assertEqual(ini_get('max_execution_time'), 100, t("Check time limit can't be reduced."));
+
+    // Check we can increase the time limit.
+    drupal_set_time_limit(101);
+    $this->assertEqual(ini_get('max_execution_time'), 101, t('Check time limit can be increased.'));
+
+    // Check we can set the time limit to 0 (unlimited).
+    drupal_set_time_limit(0);
+    $this->assertEqual(ini_get('max_execution_time'), 0, t('Check time limit can be set to unlimited.'));
+  }
+}
--- includes/locale.inc.1.195	Sat Nov 29 15:23:51 2008
+++ includes/locale.inc	Sat Nov 29 17:07:23 2008
@@ -993,10 +993,8 @@ function locale_add_language($langcode, 
  *   Text group to import PO file into (eg. 'default' for interface translations)
  */
 function _locale_import_po($file, $langcode, $mode, $group = NULL) {
-  // If not in 'safe mode', increase the maximum execution time.
-  if (!ini_get('safe_mode')) {
-    set_time_limit(240);
-  }
+  // Try to increase the maximum execution time.
+  drupal_set_time_limit(240);
 
   // Check if we have the language already in the database.
   if (!db_fetch_object(db_query("SELECT language FROM {languages} WHERE language = '%s'", $langcode))) {
--- modules/node/node.module.1.998	Sat Nov 29 15:23:52 2008
+++ modules/node/node.module	Sat Nov 29 17:05:58 2008
@@ -2440,10 +2440,9 @@ function node_access_rebuild($batch_mode
       batch_set($batch);
     }
     else {
-      // If not in 'safe mode', increase the maximum execution time.
-      if (!ini_get('safe_mode')) {
-        set_time_limit(240);
-      }
+      // Try to increase the maximum execution time.
+      drupal_set_time_limit(240);
+
       $result = db_query("SELECT nid FROM {node}");
       while ($node = db_fetch_object($result)) {
         $loaded_node = node_load($node->nid, NULL, TRUE);
--- scripts/run-tests.sh.1.18	Sat Nov 29 15:23:53 2008
+++ scripts/run-tests.sh	Sat Nov 29 17:04:31 2008
@@ -64,10 +64,8 @@ if ($args['list']) {
 
 $test_list = simpletest_script_get_test_list();
 
-// If not in 'safe mode', increase the maximum execution time.
-if (!ini_get('safe_mode')) {
-  set_time_limit(0);
-}
+// Try to set unlimited execution time.
+drupal_set_time_limit(0);
 
 simpletest_script_reporter_init();
 
