Index: wp-admin/options.php
===================================================================
--- wp-admin/options.php	(revision 22134)
+++ wp-admin/options.php	(working copy)
@@ -62,7 +62,7 @@
 	'general' => array( 'blogname', 'blogdescription', 'gmt_offset', 'date_format', 'time_format', 'start_of_week', 'timezone_string' ),
 	'discussion' => array( 'default_pingback_flag', 'default_ping_status', 'default_comment_status', 'comments_notify', 'moderation_notify', 'comment_moderation', 'require_name_email', 'comment_whitelist', 'comment_max_links', 'moderation_keys', 'blacklist_keys', 'show_avatars', 'avatar_rating', 'avatar_default', 'close_comments_for_old_posts', 'close_comments_days_old', 'thread_comments', 'thread_comments_depth', 'page_comments', 'comments_per_page', 'default_comments_page', 'comment_order', 'comment_registration' ),
 	'media' => array( 'thumbnail_size_w', 'thumbnail_size_h', 'thumbnail_crop', 'medium_size_w', 'medium_size_h', 'large_size_w', 'large_size_h', 'image_default_size', 'image_default_align', 'image_default_link_type' ),
-	'reading' => array( 'posts_per_page', 'posts_per_rss', 'rss_use_excerpt', 'show_on_front', 'page_on_front', 'page_for_posts', 'blog_public' ),
+	'reading' => array( 'posts_per_page', 'posts_per_rss', 'rss_use_excerpt', 'show_on_front', 'blog_public' ),
 	'writing' => array( 'use_smilies', 'default_category', 'default_email_category', 'use_balanceTags', 'default_link_category', 'default_post_format' )
 );
 $whitelist_options['misc'] = $whitelist_options['options'] = $whitelist_options['privacy'] = array();
Index: wp-admin/includes/post.php
===================================================================
--- wp-admin/includes/post.php	(revision 22134)
+++ wp-admin/includes/post.php	(working copy)
@@ -1337,22 +1337,37 @@
  * @since 3.5.0
  * @access private
  */
-function _create_pages_for_reading_settings() {
-	// If we're saving the Reading Settings screen, intercept.
-	if ( ! isset( $_POST['show_on_front'] ) )
-		return;
+function _create_pages_for_reading_settings( $show_on_front_value ) {
+	// If we're not saving the Reading Settings screen, don't intercept.
+	if ( ! $_POST || ! strpos( wp_get_referer(), 'options-reading.php' ) )
+		return $show_on_front_value;
 
+	if ( 'posts' == $show_on_front_value ) {
+		update_option( 'page_on_front', 0 );
+		update_option( 'page_for_posts', 0 );
+		return $show_on_front_value;
+	}
+
 	// If a new front page was meant to be created, go forth and create it.
-	if ( isset( $_POST['page_on_front'] ) && 'new' == $_POST['page_on_front'] ) {
+	if ( 'new' == $_POST['page_on_front'] ) {
+
+		// If the user can't create pages, revert.
 		if ( ! current_user_can( 'create_posts', 'page' ) ) {
-			$_POST['page_on_front'] = 0;
-			$_POST['show_on_front'] = 'posts';
+			// If an existing page is set, keep things as is, rather than reverting to showing posts.
+			if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ) {
+				$show_on_front_value = 'page';
+			} else {
+				$show_on_front_value = 'posts';
+				update_option( 'page_on_front', 0 );
+				update_option( 'page_for_posts', 0 );
+			}
 			add_settings_error( 'page_on_front', __( 'You are not allowed to create pages on this site.' ) );
+			return $show_on_front_value;
 		}
 
 		$existing_page = get_page_by_title( stripslashes( $_POST['page_on_front_title'] ) );
 
-		// If page already exists and it's public, there's no need to create a new page
+		// If page already exists and it's public, there's no need to create a new page.
 		if ( $existing_page && 'publish' == $existing_page->post_status ) {
 			$page_id = $existing_page->ID;
 		} else {
@@ -1364,38 +1379,45 @@
 				'ping_status' => 'closed',
 				// @todo Create some sort of a 'context' in postmeta so we know we created a page through these means.
 				//       Consider then showing that context in the list table as a good-first-step.
-			), true );
+			) );
 		}
 
-		// Make sure page_on_front is properly saved by options.php.
-		if ( is_wp_error( $page_id ) )
-			$_POST['page_on_front'] = 0;
-		else
-			$_POST['page_on_front'] = $page_id;
+		if ( $page_id ) {
+			update_option( 'page_on_front', $page_id );
+		// If we can't save it, revert.
+		} elseif ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ) {
+			$show_on_front_value = 'page';
+		} else {
+			$show_on_front_value = 'posts';
+			update_option( 'page_on_front', 0 );
+			update_option( 'page_for_posts', 0 );
+			return $show_on_front_value;
+		}
+	} else {
+		update_option( 'page_on_front', $_POST['page_on_front'] );
 	}
 
 	// If a page for posts was meant to be specified, update/create it.
-	if ( ! isset( $_POST['page_for_posts'] ) )
-		return;
+	if ( ! isset( $_POST['page_for_posts'] ) ) {
+		update_option( 'page_for_posts', 0 );
+		return $show_on_front_value;
+	}
 
 	$page_for_posts = (int) $_POST['page_for_posts'];
+
 	if ( ! $page_for_posts || ! $page = get_post( $page_for_posts, ARRAY_A ) ) {
-		$_POST['page_for_posts'] = 0;
-		return;
+		update_option( 'page_for_posts', 0 );
+		return $show_on_front_value;
 	}
 
-	// @todo The UI (see @todo's in options-reading) should cover the next 3 conditionals,
-	//       which means we shouldn't need to bother with setting a settings error here.
-	//       However, we may wish to restore settings before bailing, beyond setting
-	//       page_for_posts to 0 (which we then expect to get cleaned up by options.php).
 	if ( 'page' != $page['post_type'] || ! current_user_can( 'edit_post', $page_for_posts ) ) {
-		$_POST['page_for_posts'] = 0;
-		return;
+		update_option( 'page_for_posts', 0 );
+		return $show_on_front_value;
 	}
 
 	if ( 'publish' != $page['post_status'] && ! current_user_can( 'publish_post', $page_for_posts ) ) {
-		$_POST['page_for_posts'] = 0;
-		return;
+		update_option( 'page_for_posts', 0 );
+		return $show_on_front_value;
 	}
 
 	$args = add_magic_quotes( $page );
@@ -1407,8 +1429,9 @@
 		$args['ping_status'] = 'closed';
 	}
 
-	$page_id = wp_insert_post( $args, true );
-	if ( is_wp_error( $page_id ) )
-		$_POST['page_for_posts'] = 0;
+	$page_id = wp_insert_post( $args );
+	update_option( 'page_for_posts', $page_id );
+
+	return $show_on_front_value;
 }
-add_filter( 'admin_init', '_create_pages_for_reading_settings' );
+add_filter( 'sanitize_option_show_on_front', '_create_pages_for_reading_settings' );
