diff --git a/includes/menu.inc b/includes/menu.inc
index 53b41ee..62e89e7 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -2707,31 +2707,33 @@ function menu_reset_static_cache() {
  *   in parallel and the current thread just waited for completion.
  */
 function menu_rebuild() {
+  global $conf;
   if (!lock_acquire('menu_rebuild')) {
     // Wait for another request that is already doing this work.
     // We choose to block here since otherwise the router item may not
     // be available in menu_execute_active_handler() resulting in a 404.
     lock_wait('menu_rebuild');
 
-    // Another process has built the menu for us, however, there are
-    // still cache loaded variables in this processes that think we 
-    // need to rebuild the menu. So before we return, lets alter those
-    // variables for this process only (no writes to the database).
-    global $conf;
+    // Refresh all variables written while waiting for the lock. This will
+    // ensure that $conf['menu_masks'] is set correctly.
+    variable_initialize($conf);
+    // Ensure that no further rebuild is triggered by this process.
     if (isset($conf['menu_rebuild_needed'])) {
       unset($conf['menu_rebuild_needed']);
     }
+    return FALSE;
+  }
 
-    // The menu_masks variable needs to be put into the local
-    // variables array $conf to prevent rebulding in this process.
-    // We can read this out of the updated variables table.
-    $menu_masks_data = db_query('SELECT value FROM {variable} WHERE name = :name', array(':name' => 'menu_masks'))->fetchField();
-    if ($menu_masks_data) {
-      $conf['menu_masks'] = unserialize($menu_masks_data);
-    }
+  // Account for a race condition where the menu needed rebuilding at the
+  // beginning of this request, but was subsequently rebuilt by another process
+  // in the meantime. In this case, avoid another rebuild.
+  variable_initialize($conf);
+  if (!variable_get('menu_rebuild_needed')) {
+    lock_release('menu_rebuild');
     return FALSE;
   }
 
+
   $transaction = db_transaction();
 
   try {
@@ -2746,13 +2748,22 @@ function menu_rebuild() {
       variable_set('menu_rebuild_needed', TRUE);
     }
     else {
-      variable_del('menu_rebuild_needed');
+      // Explicitly set the value to false so that variable_initialize() calls
+      // elsewhere in this function will overwrite $conf to FALSE when we hit
+      // race conditions.
+      variable_set('menu_rebuild_needed', FALSE);
     }
   }
   catch (Exception $e) {
     $transaction->rollback();
     watchdog_exception('menu', $e);
   }
+  // Explicitly commit the transaction now, this ensures that the database
+  // operations during the menu rebuild are committed before the lock is made
+  // available again, since locks may not always reside in the same database
+  // connection. The lock is acquired outside of the transaction so should also
+  // be released outside of it.
+  unset($transaction);
 
   lock_release('menu_rebuild');
   return TRUE;
