diff --git a/includes/session.inc b/includes/session.inc
index 25aa3475e9..3230c0ed2a 100644
--- a/includes/session.inc
+++ b/includes/session.inc
@@ -371,8 +371,11 @@ function drupal_session_regenerate() {
 
   if (drupal_session_started()) {
     $old_session_id = session_id();
+    _drupal_session_regenerate_existing();
+  }
+  else {
+    session_id(drupal_random_key());
   }
-  session_id(drupal_random_key());
 
   if (isset($old_session_id)) {
     $params = session_get_cookie_params();
@@ -412,6 +415,25 @@ function drupal_session_regenerate() {
   date_default_timezone_set(drupal_get_user_timezone());
 }
 
+/**
+ * Regenerates an existing session.
+ */
+function _drupal_session_regenerate_existing() {
+  global $user;
+  // Preserve existing settings for the saving of sessions.
+  $original_save_session_status = drupal_save_session();
+  // Turn off saving of sessions.
+  drupal_save_session(FALSE);
+  session_write_close();
+  drupal_session_started(FALSE);
+  // Preserve and restore user object, as starting session will reset it.
+  $original_user = $user;
+  drupal_session_start();
+  $user = $original_user;
+  // Restore the original settings for the saving of sessions.
+  drupal_save_session($original_save_session_status);
+}
+
 /**
  * Session handler assigned by session_set_save_handler().
  *
diff --git a/modules/user/tests/user_session_test.info b/modules/user/tests/user_session_test.info
new file mode 100644
index 0000000000..91f2f20c7c
--- /dev/null
+++ b/modules/user/tests/user_session_test.info
@@ -0,0 +1,6 @@
+name = "User module session tests"
+description = "Support module for user session testing."
+package = Testing
+version = VERSION
+core = 7.x
+hidden = TRUE
diff --git a/modules/user/tests/user_session_test.module b/modules/user/tests/user_session_test.module
new file mode 100644
index 0000000000..3743c78059
--- /dev/null
+++ b/modules/user/tests/user_session_test.module
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Dummy module implementing a page callback to create an anon session.
+ */
+
+/**
+ * Implements hook_menu().
+ *
+ * Sets up a form that allows a user to validate password.
+ */
+function user_session_test_menu() {
+  $items = array();
+  $items['user_session_test_anon_session'] = array(
+    'page callback' => 'user_session_test_anon_session',
+    'access callback' => TRUE,
+  );
+  return $items;
+}
+
+/**
+ * Page callback.
+ *
+ * Creates an anonymous user session.
+ */
+function user_session_test_anon_session() {
+  $data = 'This dummy data will be stored in a user session.';
+  $_SESSION[__FUNCTION__] = $data;
+  return $data;
+}
diff --git a/modules/user/user.test b/modules/user/user.test
index fb82c93c22..835154b25f 100644
--- a/modules/user/user.test
+++ b/modules/user/user.test
@@ -321,6 +321,10 @@ class UserLoginTestCase extends DrupalWebTestCase {
     );
   }
 
+  function setUp() {
+    parent::setUp('user_session_test');
+  }
+
   /**
    * Test the global login flood control.
    */
@@ -421,6 +425,17 @@ class UserLoginTestCase extends DrupalWebTestCase {
     $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_HASH_COUNT + 1);
   }
 
+  /**
+   * Test logging in when an anon session already exists.
+   */
+  function testLoginWithAnonSession() {
+    // Visit the callback to generate a session for this anon user.
+    $this->drupalGet('user_session_test_anon_session');
+    // Now login.
+    $account = $this->drupalCreateUser(array());
+    $this->drupalLogin($account);
+  }
+
   /**
    * Make an unsuccessful login attempt.
    *
