Index: src/wp-admin/includes/plugin.php
===================================================================
--- src/wp-admin/includes/plugin.php	(revision 25555)
+++ src/wp-admin/includes/plugin.php	(working copy)
@@ -541,25 +541,31 @@
 
 		if ( ! $silent ) {
 			/**
-			 * Fires before a plugin is activated in activate_plugin() when the $silent parameter is false.
+			 * Fires before a plugin is activated in activate_plugin().
+			 *
+			 * Does not fire when a plugin is "silently" activated, such as during updates.
 			 * 
 			 * @since 2.9.0
 			 *
 			 * @param string $plugin       Plugin path to main plugin file with plugin data.
-			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
+			 * @param bool   $network_wide Whether the plugin is being enabled for all sites in the network
 			 *                             or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'activate_plugin', $plugin, $network_wide );
 
 			/**
-			 * Fires before a plugin is activated in activate_plugin() when the $silent parameter is false.
+			 * Fires as a plugin is being activated in activate_plugin().
+			 *
+			 * Does not fire when a plugin is "silently" activated, such as during updates.
 			 * 
+			 * This is the hook used by register_activation_hook().
+			 *
 			 * The action concatenates the 'activate_' prefix with the $plugin value passed to
 			 * activate_plugin() to create a dynamically-named action.
 			 * 
 			 * @since 2.0.0
 			 *
-			 * @param bool $network_wide Whether to enable the plugin for all sites in the network
+			 * @param bool $network_wide Whether the plugin is being enabled for all sites in the network
 			 *                           or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'activate_' . $plugin, $network_wide );
@@ -566,9 +572,13 @@
 		}
 
 		if ( $network_wide ) {
+			// Refresh this in case a plugin performed any (de)activations.
+			$current = get_site_option( 'active_sitewide_plugins', array() );
 			$current[$plugin] = time();
 			update_site_option( 'active_sitewide_plugins', $current );
 		} else {
+			// Refresh this in case a plugin performed any (de)activations.
+			$current = get_option( 'active_plugins', array() );
 			$current[] = $plugin;
 			sort($current);
 			update_option('active_plugins', $current);
@@ -576,13 +586,15 @@
 
 		if ( ! $silent ) {
 			/**
-			 * Fires after a plugin has been activated in activate_plugin() when the $silent parameter is false.
+			 * Fires after a plugin has been activated in activate_plugin().
+			 *
+			 * Does not fire when a plugin is "silently" activated, such as during updates.
 			 * 
 			 * @since 2.9.0
 			 *
 			 * @param string $plugin       Plugin path to main plugin file with plugin data.
-			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
-			 *                             or just the current site. Multisite only. Default is false.
+			 * @param bool $network_wide Whether the plugin was enabled for all sites in the network
+			 *                           or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'activated_plugin', $plugin, $network_wide );
 		}
@@ -611,10 +623,8 @@
  * 	A value of null (the default) will deactivate plugins for both the site and the network.
  */
 function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) {
-	if ( is_multisite() )
-		$network_current = get_site_option( 'active_sitewide_plugins', array() );
 	$current = get_option( 'active_plugins', array() );
-	$do_blog = $do_network = false;
+	$do_blog = $do_network = array();
 
 	foreach ( (array) $plugins as $plugin ) {
 		$plugin = plugin_basename( trim( $plugin ) );
@@ -623,23 +633,24 @@
 
 		$network_deactivating = false !== $network_wide && is_plugin_active_for_network( $plugin );
 
-		if ( ! $silent )
+		if ( ! $silent ) {
 			/**
-			 * Fires for each plugin being deactivated in deactivate_plugins(), before deactivation
-			 * and when the $silent parameter is false.
+			 * Fires for each plugin being deactivated in deactivate_plugins().
+			 *
+			 * Does not fire when a plugin is "silently" deactivated, such as during updates.
 			 * 
 			 * @since 2.9.0
 			 *
 			 * @param string $plugin               Plugin path to main plugin file with plugin data.
-			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network 
+			 * @param bool   $network_deactivating Whether the plugin is being deactivated for all sites in the network
 			 *                                     or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
+		}
 
 		if ( false !== $network_wide ) {
 			if ( is_plugin_active_for_network( $plugin ) ) {
-				$do_network = true;
-				unset( $network_current[ $plugin ] );
+				$do_network[ $plugin ] = true;
 			} elseif ( $network_wide ) {
 				continue;
 			}
@@ -648,34 +659,35 @@
 		if ( true !== $network_wide ) {
 			$key = array_search( $plugin, $current );
 			if ( false !== $key ) {
-				$do_blog = true;
-				unset( $current[ $key ] );
+				$do_blog[ $key ] = true;
 			}
 		}
 
 		if ( ! $silent ) {
 			/**
-			 * Fires for each plugin being deactivated in deactivate_plugins(), after deactivation
-			 * and when the $silent parameter is false.
+			 * Fires for each plugin being deactivated in deactivate_plugins().
+			 *
+			 * Does not fire when a plugin is "silently" deactivated, such as during updates.
 			 * 
+			 * This is the hook used by register_deactivation_hook().
+			 *
 			 * The action concatenates the 'deactivate_' prefix with the plugin's basename
 			 * to create a dynamically-named action.
 			 * 
 			 * @since 2.0.0
 			 *
-			 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network 
+			 * @param bool $network_deactivating Whether the plugin is being deactivated for all sites in the network
 			 *                                   or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'deactivate_' . $plugin, $network_deactivating );
 
 			/**
-			 * Fires for each plugin being deactivated in deactivate_plugins(), after deactivation
-			 * and when the $silent parameter is false.
+			 * Fires for each plugin being deactivated in deactivate_plugins()
 			 * 
 			 * @since 2.9.0
 			 *
 			 * @param string $plugin               Plugin path to main plugin file with plugin data.
-			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network 
+			 * @param bool   $network_deactivating Whether the plugin was deactivated for all sites in the network
 			 *                                     or just the current site. Multisite only. Default is false.
 			 */
 			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
@@ -682,10 +694,16 @@
 		}
 	}
 
-	if ( $do_blog )
+	if ( $do_blog ) {
+		$current = get_option( 'active_plugins', array() );
+		$current = array_diff_key( $current, $do_blog );
 		update_option('active_plugins', $current);
-	if ( $do_network )
+	}
+	if ( $do_network ) {
+		$network_current = get_site_option( 'active_sitewide_plugins', array() );
+		$network_current = array_diff_key( $network_current, $do_network );
 		update_site_option( 'active_sitewide_plugins', $network_current );
+	}
 }
 
 /**
