diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b4bdec2bc72..8e2311a1eb3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+Mon Dec 30 00:14:06 1996  Doug Evans  <dje@seba.cygnus.com>
+
+	* remote-sim.c (gdbsim_open_p): New static local.
+	(gdbsim_open): Call unpush_target if sim open.  Set gdbsim_open_p.
+	(gdbsim_close): Only call sim_close if sim open.  Reset gdbsim_open_p.
+
 Sun Dec 29 09:15:03 1996  Mark Alexander  <marka@cygnus.com>
 
 	* config/i386/xm-windows.h: Make SIGTRAP and SIGQUIT consistent
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index e9c32dbab57..3b0ddb45970 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -93,6 +93,11 @@ extern struct target_ops gdbsim_ops;
 
 static int program_loaded = 0;
 
+/* We must keep track of whether the simulator has been opened or not because
+   GDB can call a target's close routine twice, but sim_close doesn't allow
+   this.  */
+static int gdbsim_open_p = 0;
+
 static void
 dump_mem (buf, len)
      char *buf;
@@ -380,9 +385,19 @@ gdbsim_open (args, from_tty)
   if (sr_get_debug ())
     printf_filtered ("gdbsim_open: args \"%s\"\n", args ? args : "(null)");
 
+  /* Remove current simulator if one exists.  Only do this if the simulator
+     has been opened because sim_close requires it.
+     This is important because the call to push_target below will cause
+     sim_close to be called if the simulator is already open, but push_target
+     is called after sim_open!  We can't move the call to push_target before
+     the call to sim_open because sim_open may invoke `error'.  */
+  if (gdbsim_open_p)
+    unpush_target (&gdbsim_ops);
+
   init_callbacks ();
 
   sim_open (args);
+  gdbsim_open_p = 1;
 
   push_target (&gdbsim_ops);
   target_fetch_registers (-1);
@@ -407,7 +422,11 @@ gdbsim_close (quitting)
 
   program_loaded = 0;
 
-  sim_close (quitting);
+  if (gdbsim_open_p)
+    {
+      sim_close (quitting);
+      gdbsim_open_p = 0;
+    }
 
   end_callbacks ();
 }