This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: "disconnect" command


This patch got tabled shortly before 5.3, due to bad timing on my part. 
Now here we are coming up on 6.0 and my timing's no better... this is
the first of several old patches that I would like to see included in
6.0, assuming I get the time to revisit them all.

Refresher on this one: the patch adds a "disconnect" commad, and
implements it for remote targets.  "disconnect" leaves the target
stopped, while "detach" usually resumes it.  Useful with kgdb,
gdbserver, et cetera.

I've included the gdbserver portion of the patch this time, too.

There was a consensus on this patch the last time I posted it, but it's
been so long that I'd like a thumbs-up from another maintainer first.
I've corrected the doc problems; Andrew, there's still no MI testcase,
because I could not figure out a reasonable way to write one without
leaving a dangling process around.  Re-attaching to it to kill it
properly, from within the testsuite, ranges from hard to really hard.

Thoughts?  OK?

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer

2003-06-14  Daniel Jacobowitz  <drow@mvista.com>

        * NEWS: Mention gdbserver detach change and "disconnect" command.
        * infcmd.c (disconnect_command): New function.
        (_initialize_infcmd): Add ``disconnect'' command.
        * remote.c (remote_async_detach): Delete.
        (remote_detach): Merge remote_async_detach.
        (remote_disconnect): New.
        (init_remote_ops): Set to_disconnect.
        (init_remote_cisco_ops): Likewise.
        (init_remote_async_ops): Likewise.  Use remote_detach.
        * target.c (cleanup_target): Default to_disconnect.
        (update_current_target): Inherit to_disconnect.
        (target_disconnect, debug_to_disconnect): New functions.
        (setup_target_debug): Set to_disconnect.
        * target.h (struct target_ops): Add to_disconnect.
        (target_disconnect): Add prototype.

2003-06-14  Daniel Jacobowitz  <drow@mvista.com>

	* linux-low.c: Move comment to linux_thread_alive where it belonged.
	(linux_detach_one_process, linux_detach): New functions.
	(linux_target_ops): Add linux_detach.
	* server.c (main): Handle 'D' packet.
	* target.h (struct target_ops): Add "detach" member.
	(detach_inferior): Define.

2003-06-14  Daniel Jacobowitz  <drow@mvista.com>

        * gdb.texinfo (Debug Session): Document "disconnect" command.
	(GDB/MI Target Manipulation): Document "-target-disconnect".

2003-06-14  Daniel Jacobowitz  <drow@mvista.com>

        * mi-cmds.c (mi_cmds): Add "-target-disconnect".


Index: gdb/NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.109
diff -u -p -r1.109 NEWS
--- gdb/NEWS	13 May 2003 05:40:34 -0000	1.109
+++ gdb/NEWS	14 Jun 2003 04:05:25 -0000
@@ -3,6 +3,12 @@
 
 *** Changes since GDB 5.3:
 
+* The meaning of "detach" has changed for gdbserver
+
+The "detach" command will now resume the application, as documented.  To
+disconnect from gdbserver and leave it stopped, use the new "disconnect"
+command.
+
 * d10v `regs' command deprecated
 
 The `info registers' command has been updated so that it displays the
Index: gdb/infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.81
diff -u -p -r1.81 infcmd.c
--- gdb/infcmd.c	11 Jun 2003 19:38:26 -0000	1.81
+++ gdb/infcmd.c	14 Jun 2003 04:05:25 -0000
@@ -81,6 +81,8 @@ static void float_info (char *, int);
 
 static void detach_command (char *, int);
 
+static void disconnect_command (char *, int);
+
 static void unset_environment_command (char *, int);
 
 static void set_environment_command (char *, int);
@@ -1876,6 +1878,26 @@ detach_command (char *args, int from_tty
     detach_hook ();
 }
 
+/* Disconnect from the current target without resuming it (leaving it
+   waiting for a debugger).
+
+   We'd better not have left any breakpoints in the program or the
+   next debugger will get confused.  Currently only supported for some
+   remote targets, since the normal attach mechanisms don't work on
+   stopped processes on some native platforms (e.g. GNU/Linux).  */
+
+static void
+disconnect_command (char *args, int from_tty)
+{
+  dont_repeat ();		/* Not for the faint of heart */
+  target_disconnect (args, from_tty);
+#if defined(SOLIB_RESTART)
+  SOLIB_RESTART ();
+#endif
+  if (detach_hook)
+    detach_hook ();
+}
+
 /* Stop the execution of the target while running in async mode, in
    the backgound. */
 void
@@ -2013,6 +2035,11 @@ to specify the program, and to load its 
 	   "Detach a process or file previously attached.\n\
 If a process, it is no longer traced, and it continues its execution.  If\n\
 you were debugging a file, the file is closed and gdb no longer accesses it.");
+
+  add_com ("disconnect", class_run, disconnect_command,
+	   "Disconnect from a target.\n\
+The target will wait for another debugger to connect.  Not available for\n\
+all targets.");
 
   add_com ("signal", class_run, signal_command,
 	   "Continue program giving it signal specified by the argument.\n\
Index: gdb/remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.105
diff -u -p -r1.105 remote.c
--- gdb/remote.c	10 Jun 2003 14:37:04 -0000	1.105
+++ gdb/remote.c	14 Jun 2003 04:05:26 -0000
@@ -126,7 +126,6 @@ static void remote_async_kill (void);
 static int tohex (int nib);
 
 static void remote_detach (char *args, int from_tty);
-static void remote_async_detach (char *args, int from_tty);
 
 static void remote_interrupt (int signo);
 
@@ -2421,15 +2420,19 @@ remote_detach (char *args, int from_tty)
   strcpy (buf, "D");
   remote_send (buf, (rs->remote_packet_size));
 
+  /* Unregister the file descriptor from the event loop. */
+  if (target_is_async_p ())
+    serial_async (remote_desc, NULL, 0);
+
   target_mourn_inferior ();
   if (from_tty)
     puts_filtered ("Ending remote debugging.\n");
-
 }
 
-/* Same as remote_detach, but with async support. */
+/* Same as remote_detach, but don't send the "D" packet; just disconnect.  */
+
 static void
-remote_async_detach (char *args, int from_tty)
+remote_disconnect (char *args, int from_tty)
 {
   struct remote_state *rs = get_remote_state ();
   char *buf = alloca (rs->remote_packet_size);
@@ -2437,10 +2440,6 @@ remote_async_detach (char *args, int fro
   if (args)
     error ("Argument given to \"detach\" when remotely debugging.");
 
-  /* Tell the remote target to detach.  */
-  strcpy (buf, "D");
-  remote_send (buf, (rs->remote_packet_size));
-
   /* Unregister the file descriptor from the event loop. */
   if (target_is_async_p ())
     serial_async (remote_desc, NULL, 0);
@@ -5435,6 +5434,7 @@ Specify the serial device it is connecte
   remote_ops.to_open = remote_open;
   remote_ops.to_close = remote_close;
   remote_ops.to_detach = remote_detach;
+  remote_ops.to_disconnect = remote_disconnect;
   remote_ops.to_resume = remote_resume;
   remote_ops.to_wait = remote_wait;
   remote_ops.to_fetch_registers = remote_fetch_registers;
@@ -5855,6 +5855,7 @@ Specify the serial device it is connecte
   remote_cisco_ops.to_open = remote_cisco_open;
   remote_cisco_ops.to_close = remote_cisco_close;
   remote_cisco_ops.to_detach = remote_detach;
+  remote_cisco_ops.to_disconnect = remote_disconnect;
   remote_cisco_ops.to_resume = remote_resume;
   remote_cisco_ops.to_wait = remote_cisco_wait;
   remote_cisco_ops.to_fetch_registers = remote_fetch_registers;
@@ -5950,7 +5951,8 @@ init_remote_async_ops (void)
 Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_open = remote_async_open;
   remote_async_ops.to_close = remote_close;
-  remote_async_ops.to_detach = remote_async_detach;
+  remote_async_ops.to_detach = remote_detach;
+  remote_async_ops.to_disconnect = remote_disconnect;
   remote_async_ops.to_resume = remote_async_resume;
   remote_async_ops.to_wait = remote_async_wait;
   remote_async_ops.to_fetch_registers = remote_fetch_registers;
Index: gdb/target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.52
diff -u -p -r1.52 target.c
--- gdb/target.c	8 May 2003 20:52:48 -0000	1.52
+++ gdb/target.c	14 Jun 2003 04:05:26 -0000
@@ -95,6 +95,8 @@ static void debug_to_attach (char *, int
 
 static void debug_to_detach (char *, int);
 
+static void debug_to_disconnect (char *, int);
+
 static void debug_to_resume (ptid_t, int, enum target_signal);
 
 static ptid_t debug_to_wait (ptid_t, struct target_waitstatus *);
@@ -371,6 +373,9 @@ cleanup_target (struct target_ops *t)
   de_fault (to_detach, 
 	    (void (*) (char *, int)) 
 	    target_ignore);
+  de_fault (to_disconnect, 
+	    (void (*) (char *, int)) 
+	    tcomplain);
   de_fault (to_resume, 
 	    (void (*) (ptid_t, int, enum target_signal)) 
 	    noprocess);
@@ -556,6 +561,7 @@ update_current_target (void)
       INHERIT (to_attach, t);
       INHERIT (to_post_attach, t);
       INHERIT (to_detach, t);
+      INHERIT (to_disconnect, t);
       INHERIT (to_resume, t);
       INHERIT (to_wait, t);
       INHERIT (to_post_wait, t);
@@ -1141,6 +1147,16 @@ target_detach (char *args, int from_tty)
 }
 
 void
+target_disconnect (char *args, int from_tty)
+{
+  /* Handle any optimized stores to the inferior.  */
+#ifdef DO_DEFERRED_STORES
+  DO_DEFERRED_STORES;
+#endif
+  (current_target.to_disconnect) (args, from_tty);
+}
+
+void
 target_link (char *modname, CORE_ADDR *t_reloc)
 {
   if (STREQ (current_target.to_shortname, "rombug"))
@@ -1562,6 +1578,15 @@ debug_to_detach (char *args, int from_tt
 }
 
 static void
+debug_to_disconnect (char *args, int from_tty)
+{
+  debug_target.to_disconnect (args, from_tty);
+
+  fprintf_unfiltered (gdb_stdlog, "target_disconnect (%s, %d)\n",
+		      args, from_tty);
+}
+
+static void
 debug_to_resume (ptid_t ptid, int step, enum target_signal siggnal)
 {
   debug_target.to_resume (ptid, step, siggnal);
@@ -2202,6 +2227,7 @@ setup_target_debug (void)
   current_target.to_attach = debug_to_attach;
   current_target.to_post_attach = debug_to_post_attach;
   current_target.to_detach = debug_to_detach;
+  current_target.to_disconnect = debug_to_disconnect;
   current_target.to_resume = debug_to_resume;
   current_target.to_wait = debug_to_wait;
   current_target.to_post_wait = debug_to_post_wait;
Index: gdb/target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.40
diff -u -p -r1.40 target.h
--- gdb/target.h	2 Jun 2003 23:20:47 -0000	1.40
+++ gdb/target.h	14 Jun 2003 04:05:26 -0000
@@ -198,6 +198,7 @@ struct target_ops
     void (*to_attach) (char *, int);
     void (*to_post_attach) (int);
     void (*to_detach) (char *, int);
+    void (*to_disconnect) (char *, int);
     void (*to_resume) (ptid_t, int, enum target_signal);
     ptid_t (*to_wait) (ptid_t, struct target_waitstatus *);
     void (*to_post_wait) (ptid_t, int);
@@ -413,6 +414,11 @@ extern struct target_stack_item *target_
    says whether to be verbose or not.  */
 
 extern void target_detach (char *, int);
+
+/* Disconnect from the current target without resuming it (leaving it
+   waiting for a debugger).  */
+
+extern void target_disconnect (char *, int);
 
 /* Resume execution of the target process PTID.  STEP says whether to
    single-step or to run free; SIGGNAL is the signal to be given to
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.164
diff -u -p -r1.164 gdb.texinfo
--- gdb/doc/gdb.texinfo	9 Jun 2003 21:12:19 -0000	1.164
+++ gdb/doc/gdb.texinfo	14 Jun 2003 04:05:29 -0000
@@ -11069,6 +11069,10 @@ step and continue the remote program.
 To resume the remote program and stop debugging it, use the @code{detach}
 command.
 
+@kindex disconnect
+To disconnect from the remote program and let it wait for another debugger
+to connect, use the @code{disconnect} command.
+
 @cindex interrupting remote programs
 @cindex remote programs, interrupting
 Whenever @value{GDBN} is waiting for the remote program, if you type the
@@ -17392,6 +17396,31 @@ The corresponding @value{GDBN} command i
 @end smallexample
 
 
+@subheading The @code{-target-disconnect} Command
+@findex -target-disconnect
+
+@subsubheading Synopsis
+
+@example
+ -target-disconnect
+@end example
+
+Disconnect from the remote target.  There's no output.
+
+@subsubheading @value{GDBN} command
+
+The corresponding @value{GDBN} command is @samp{disconnect}.
+
+@subsubheading Example
+
+@smallexample
+(@value{GDBP})
+-target-disconnect
+^done
+(@value{GDBP})
+@end smallexample
+
+
 @subheading The @code{-target-download} Command
 @findex -target-download
 
@@ -19775,7 +19804,7 @@ Toggle debug flag.
 @cindex @code{D} packet
 
 Detach @value{GDBN} from the remote system.  Sent to the remote target
-before @value{GDBN} disconnects.
+before @value{GDBN} disconnects via the @code{detach} command.
 
 Reply:
 @table @samp
Index: gdb/gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.23
diff -u -p -r1.23 linux-low.c
--- gdb/gdbserver/linux-low.c	5 Jun 2003 14:26:58 -0000	1.23
+++ gdb/gdbserver/linux-low.c	14 Jun 2003 04:05:29 -0000
@@ -234,13 +234,28 @@ linux_kill_one_process (struct inferior_
     } while (WIFSTOPPED (wstat));
 }
 
-/* Return nonzero if the given thread is still alive.  */
 static void
 linux_kill (void)
 {
   for_each_inferior (&all_threads, linux_kill_one_process);
 }
 
+static void
+linux_detach_one_process (struct inferior_list_entry *entry)
+{
+  struct thread_info *thread = (struct thread_info *) entry;
+  struct process_info *process = get_thread_process (thread);
+
+  ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
+}
+
+static void
+linux_detach (void)
+{
+  for_each_inferior (&all_threads, linux_detach_one_process);
+}
+
+/* Return nonzero if the given thread is still alive.  */
 static int
 linux_thread_alive (int tid)
 {
@@ -1249,6 +1264,7 @@ static struct target_ops linux_target_op
   linux_create_inferior,
   linux_attach,
   linux_kill,
+  linux_detach,
   linux_thread_alive,
   linux_resume,
   linux_wait,
Index: gdb/gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.14
diff -u -p -r1.14 server.c
--- gdb/gdbserver/server.c	29 Aug 2002 18:50:25 -0000	1.14
+++ gdb/gdbserver/server.c	14 Jun 2003 04:05:29 -0000
@@ -217,6 +217,28 @@ main (int argc, char *argv[])
 	    case 'd':
 	      remote_debug = !remote_debug;
 	      break;
+	    case 'D':
+	      fprintf (stderr, "Detaching from inferior\n");
+	      detach_inferior ();
+	      write_ok (own_buf);
+	      putpkt (own_buf);
+	      remote_close ();		  
+
+	      /* If we are attached, then we can exit.  Otherwise, we need to
+		 hang around doing nothing, until the child is gone.  */
+	      if (!attached)
+		{
+		  int status, ret;
+
+		  do {
+		    ret = waitpid (signal_pid, &status, 0);
+		    if (WIFEXITED (status) || WIFSIGNALED (status))
+		      break;
+		  } while (ret != -1 || errno != ECHILD);
+		}
+
+	      exit (0);
+
 	    case '!':
 	      if (attached == 0)
 		{
Index: gdb/gdbserver/target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.6
diff -u -p -r1.6 target.h
--- gdb/gdbserver/target.h	5 Jun 2003 14:26:58 -0000	1.6
+++ gdb/gdbserver/target.h	14 Jun 2003 04:05:29 -0000
@@ -48,6 +48,10 @@ struct target_ops
 
   void (*kill) (void);
 
+  /* Detach from all inferiors.  */
+
+  void (*detach) (void);
+
   /* Return 1 iff the thread with process ID PID is alive.  */
 
   int (*thread_alive) (int pid);
@@ -121,6 +125,9 @@ void set_target_ops (struct target_ops *
 
 #define kill_inferior() \
   (*the_target->kill) ()
+
+#define detach_inferior() \
+  (*the_target->detach) ()
 
 #define mythread_alive(pid) \
   (*the_target->thread_alive) (pid)
Index: gdb/mi/mi-cmds.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-cmds.c,v
retrieving revision 1.12
diff -u -p -r1.12 mi-cmds.c
--- gdb/mi/mi-cmds.c	4 May 2003 03:50:13 -0000	1.12
+++ gdb/mi/mi-cmds.c	14 Jun 2003 04:05:29 -0000
@@ -127,6 +127,7 @@ struct mi_cmd mi_cmds[] =
   {"target-attach", 0, 0},
   {"target-compare-sections", 0, 0},
   {"target-detach", "detach", 0},
+  {"target-disconnect", "disconnect", 0},
   {"target-download", 0, mi_cmd_target_download},
   {"target-exec-status", 0, 0},
   {"target-list-available-targets", 0, 0},


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]