Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.912
diff -u -p -r1.912 system.module
--- modules/system/system.module	28 Mar 2010 11:54:27 -0000	1.912
+++ modules/system/system.module	29 Mar 2010 22:24:50 -0000
@@ -2851,11 +2851,32 @@ function system_action_info() {
       'configurable' => FALSE,
       'triggers' => array(),
     ),
+    // The 'any' trigger includes view operations, which
+    // should not be subject to a redirect.
     'system_goto_action' => array(
       'type' => 'system',
       'label' => t('Redirect to URL'),
       'configurable' => TRUE,
-      'triggers' => array('any'),
+      'triggers' => array(
+        'comment_delete',
+        'comment_insert',
+        'comment_presave',
+        'comment_update',
+        'node_delete',
+        'node_insert',
+        'node_presave',
+        'node_update',
+        'user_cancel',
+        'user_delete',
+        'user_insert',
+        'user_login',
+        'user_logout',
+        'user_presave',
+        'user_update',
+        'taxonomy_term_delete',
+        'taxonomy_term_insert',
+        'taxonomy_term_update',
+      ),
     ),
   );
 }
@@ -3057,6 +3078,15 @@ function system_goto_action_submit($form
 /**
  * Redirects to a different URL.
  *
+ * We expressly cannot use drupal_goto() here. Doing so
+ * can interrupt the flow of API hooks, leading to unpredictable
+ * errors. Instead, we set a 'destination' value and allow the
+ * FormsAPI to issue a redirect after processing is complete.
+ *
+ * Note that this action is expressly banned on administrative
+ * and batch actions, which may operate on multiple entities and
+ * should not redirect away from the calling URL.
+ *
  * @param $entity
  *   Ignored.
  * @param array $context
@@ -3068,7 +3098,11 @@ function system_goto_action_submit($form
  * @ingroup actions
  */
 function system_goto_action($entity, $context) {
-  drupal_goto(token_replace($context['url'], $context));
+  // Do not redirect on administrative or batch actions.
+  $path = arg(0);
+  if ($path != 'admin' && $path != 'batch') {
+    $_GET['destination'] = token_replace($context['url'], $context);
+  }
 }
 
 /**
Index: modules/trigger/trigger.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/trigger/trigger.test,v
retrieving revision 1.30
diff -u -p -r1.30 trigger.test
--- modules/trigger/trigger.test	27 Mar 2010 18:32:06 -0000	1.30
+++ modules/trigger/trigger.test	29 Mar 2010 22:24:50 -0000
@@ -269,7 +269,7 @@ class TriggerOtherTestCase extends Trigg
     $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-insert-assign-form');
 
     // Set action variable to FALSE.
-    variable_set( $action_id, FALSE );
+    variable_set($action_id, FALSE);
 
     // Create an unblocked user
     $web_user = $this->drupalCreateUser(array('administer users'));
@@ -302,15 +302,37 @@ class TriggerOtherTestCase extends Trigg
     $edit = array('aid' => md5($aid));
     $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-login-assign-form');
 
+    // Assign a configurable action 'Redirect to URL' to the user_login trigger.
+    $url = 'contact';
+    $absolute_url = url($url, array('absolute' => TRUE));
+    $action_url = array(
+      'actions_label' => $this->randomName(16),
+      'url' => $url,
+    );
+    $aid_url = $this->configureAdvancedAction('system_goto_action', $action_url);
+    $edit = array('aid' => md5($aid_url));
+    $this->drupalPost('admin/structure/trigger/user', $edit, t('Assign'), array(), array(), 'trigger-user-login-assign-form');
+
     // Verify that the action has been assigned to the correct hook.
     $actions = trigger_get_assigned_actions('user_login');
-    $this->assertEqual(1, count($actions), t('One Action assigned to the hook'));
+    $this->assertEqual(2, count($actions), t('Two Actions assigned to the hook'));
     $this->assertEqual($actions[$aid]['label'], $action_edit['actions_label'], t('Correct action label found.'));
+    $this->assertEqual($actions[$aid_url]['label'], $action_url['actions_label'], t('Correct action label found.'));
 
     // User should get the configured message at login.
-    $contact_user = $this->drupalCreateUser(array('access site-wide contact form'));;
-    $this->drupalLogin($contact_user);
+    $contact_user = $this->drupalCreateUser(array('access site-wide contact form'));
+    $this->drupalLogout();
+
+    // Trying to login from different page to be redirected.
+    $edit = array(
+      'name' => $contact_user->name,
+      'pass' => $contact_user->pass_raw
+    );
+    $this->drupalPost('filter/tips', $edit, t('Log in'));
     $this->assertText($action_edit['message']);
+
+    // Verify that redirect happen.
+    $this->assertEqual($absolute_url, $this->url, t('Redirected successfully by the trigger.'));
   }
 
   /**
