=== modified file 'includes/cache.inc'
--- includes/cache.inc	2010-05-18 18:26:30 +0000
+++ includes/cache.inc	2010-08-15 05:09:20 +0000
@@ -417,10 +417,19 @@ class DrupalDatabaseCache implements Dru
     }
 
     try {
-      db_merge($this->bin)
-        ->key(array('cid' => $cid))
-        ->fields($fields)
-        ->execute();
+      $query = "SELECT 1 FROM {clear_cache} WHERE created > :time AND bin = :bin AND (cid = :cid OR (wildcard = 1 AND (cid IN ('', '*') OR cid LIKE :cid1)))";
+      $args = array(
+        ':time' => REQUEST_TIME - 300,
+        ':bin' => $this->bin,
+        ':cid' => $cid,
+        ':cid1' => "$cid%",
+      );
+      if (!db_query($query, $args)->fetchField()) {
+        db_merge($this->bin)
+          ->key(array('cid' => $cid))
+          ->fields($fields)
+          ->execute();
+      }
     }
     catch (Exception $e) {
       // The database may not be available, so we'll ignore cache_set requests.
@@ -429,6 +438,17 @@ class DrupalDatabaseCache implements Dru
 
   function clear($cid = NULL, $wildcard = FALSE) {
     global $user;
+    db_insert('clear_cache')
+      ->fields(array(
+        'cid' => (string) $cid,
+        'bin' => $this->bin,
+        'wildcard' => (int) $wildcard,
+        'created' => REQUEST_TIME,
+      ))
+      ->execute();
+    db_delete('clear_cache')
+      ->condition('created', REQUEST_TIME - 300, '<')
+      ->execute();
 
     if (empty($cid)) {
       if (variable_get('cache_lifetime', 0)) {

=== modified file 'modules/simpletest/tests/system_test.module'
--- modules/simpletest/tests/system_test.module	2010-08-01 23:35:01 +0000
+++ modules/simpletest/tests/system_test.module	2010-08-15 04:08:23 +0000
@@ -311,3 +311,12 @@ function _system_test_second_shutdown_fu
   throw new Exception('Drupal is <blink>awesome</blink>.');
 }
 
+function system_test_pre_render_clear_cache($elements) {
+  cache_clear_all('test', 'cache_rendercachetest');
+  return $elements;
+}
+
+function system_test_verify_cached($elements) {
+  $elements['text']['#markup'] = 'not cached';
+  return $elements;
+}

=== modified file 'modules/system/system.install'
--- modules/system/system.install	2010-07-31 12:29:31 +0000
+++ modules/system/system.install	2010-08-15 03:49:16 +0000
@@ -673,6 +673,42 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
+  $schema['clear_cache'] = array(
+    'description' => 'Holds recent cache_clear_all() commands.',
+    'fields' => array(
+      'cid' => array(
+        'description' => 'Cache ID as passed to cache_clear_all().',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'bin' => array(
+        'description' => 'The cache bin as passed to cache_clear_all().',
+        'type' => 'varchar',
+        // Longer than 75 would fail MySQL index creation.
+        'length' => 75,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'wildcard' => array(
+        'description' => 'Flag indicating whether the clear was a wildcard as passed to cache_clear_all().',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'created' => array(
+        'description' => 'A Unix timestamp indicating when the cache_clear_all() happened.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+     ),
+    'indexes' => array(
+      'full' => array('created', 'bin', 'cid', 'wildcard'),
+    ),
+  );
+
   $schema['date_format_type'] = array(
     'description' => 'Stores configured date format types.',
     'fields' => array(

=== modified file 'modules/system/system.test'
--- modules/system/system.test	2010-08-08 19:35:48 +0000
+++ modules/system/system.test	2010-08-15 04:09:31 +0000
@@ -1874,3 +1874,53 @@ class CompactModeTest extends DrupalWebT
     $this->assertTrue($this->cookies['Drupal.visitor.admin_compact_mode']['value'], t('Compact mode persists on new requests.'));
   }
 }
+
+/**
+ * Render caching test.
+ */
+class RenderCacheTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Render cache race',
+      'description' => 'Tests whether the render cache is susceptible to race conditions.',
+      'group' => 'System',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('system_test');
+    db_create_table('cache_rendercachetest', drupal_get_schema('cache'));
+  }
+
+  function testRenderCache() {
+    $markup = $this->randomString();
+    $render = array(
+      '#markup' => $markup,
+      '#cache' => array('cid' => 'test', 'bin' => 'cache_rendercachetest'),
+    );
+    $elements = $render;
+    drupal_render($elements);
+    // Verify that the text is cached.
+    $elements = $render;
+    $elements['#pre_render'][] = 'system_test_verify_cached';
+    $text = drupal_render($elements);
+    $this->assertIdentical($text, $markup, 'the render array is cached');
+  }
+
+  function testRenderCacheRace() {
+    $markup = $this->randomString();
+    $render = array(
+      '#markup' => $markup,
+      '#pre_render' => array('system_test_pre_render_clear_cache'),
+      '#cache' => array('cid' => 'test', 'bin' => 'cache_rendercachetest'),
+    );
+    $elements = $render;
+    // Render elements and clear cache at the same time.
+    drupal_render($elements);
+    // Verify that the text is not cached.
+    $elements = $render;
+    $elements['#pre_render'][] = 'system_test_verify_cached';
+    $text = drupal_render($elements);
+    $this->assertTrue(strpos($text, 'not cached') !== FALSE, 'the render array is not cached');
+  }
+}

