Re: RFC: ``detach remote''

Daniel Jacobowitz
2002-08-29T21:52:56Z

On Mon, Aug 12, 2002 at 10:47:26AM -0400, Daniel Jacobowitz wrote:
> On Mon, Aug 12, 2002 at 10:36:48AM -0400, Andrew Cagney wrote:
> >
> > >This whole question put another way:
> > > Obviously, if you start something with "run", you want to end it with
> > >"kill".
> > >
> > > Obviously, if you start something with "attach", you want to end it
> > >with "detach".
> > >
> > >[These are not hard and fast, of course. You can detach a run process
> > >or kill an attached process. But you surely see what I mean - they're
> > >logical opposites.]
> >
> > True,
> >
> > There is a tradeoff between convenience and modal behavour. Need a user
> > survey (however, I suspect the attach/detach argument would win :-).
>
> Actually, I took a couple of surveys about this. Couldn't find
> terribly many people to poll, but the general idea of having the target
> resume on detach went over well.
>
> > > If you start something with "target", how do you end it? I propose
> > >"disconnect".
> >
> > The user doesn't start something with target, they ``connect'' using
> > target. That should more strongly suggest that ``disconnect''
> > disconnects the connection :-)
>
> Pity the command is "target" instead of "connect", then :) It would
> make the pairings clearer.
>
> > The doco will end up needing a glossary.
>
> So true...
>
> What I think I'll do is submit a patch to add the "disconnect" command,
> and then commit a patch to make gdbserver detach or resume the target
> on a "D" (detach) packet.

So I did this, and I really like the result. Here's the gdb side of
the patch. It adds a command, ``disconnect'', with a new target
method. The command only works for target remote (and friends), and
disconnects without sending the "D" packet. Then I modify gdbserver to
handle the "D" packet correctly. How does this look?

--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer

2002-08-29 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.

2002-08-29 Daniel Jacobowitz <drow@mvista.com>

* gdb.texinfo: Document ``disconnect'' command.

2002-08-29 Daniel Jacobowitz <drow@mvista.com>

* mi-cmds.c (mi_cmds): Add ``-target-disconnect''.
* gdbmi.texinfo: Document ``-target-disconnect''.

Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.90
diff -u -p -r1.90 NEWS
--- NEWS 22 Aug 2002 21:52:44 -0000 1.90
+++ NEWS 29 Aug 2002 19:38:39 -0000
@@ -3,6 +3,12 @@

*** Changes since GDB 5.2:

+* 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.
+
* ``gdbserver'' now supports multi-threaded applications on some targets

Support for debugging multi-threaded applications which use
Index: infcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/infcmd.c,v
retrieving revision 1.54
diff -u -p -r1.54 infcmd.c
--- infcmd.c 21 Aug 2002 16:34:09 -0000 1.54
+++ infcmd.c 29 Aug 2002 19:38:39 -0000
@@ -72,6 +72,8 @@ static void float_info (char *, int);

static void detach_command (char *, int);

+static void disconnect_command (char *, int);
+
static void interrupt_target_command (char *args, int from_tty);

static void unset_environment_command (char *, int);
@@ -1889,6 +1891,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. */

@@ -2040,6 +2062,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: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.93
diff -u -p -r1.93 remote.c
--- remote.c 18 Aug 2002 23:17:57 -0000 1.93
+++ remote.c 29 Aug 2002 19:38:41 -0000
@@ -128,7 +128,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);

@@ -2415,15 +2414,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);
@@ -2431,10 +2434,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);
@@ -5414,6 +5413,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;
@@ -5837,6 +5837,7 @@
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;
@@ -5932,7 +5933,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: target.c
===================================================================
RCS file: /cvs/src/src/gdb/target.c,v
retrieving revision 1.40
diff -u -p -r1.40 target.c
--- target.c 26 Aug 2002 19:18:33 -0000 1.40
+++ target.c 29 Aug 2002 19:38:41 -0000
@@ -384,6 +384,9 @@ cleanup_target (struct target_ops *t)
de_fault (to_require_detach,
(void (*) (int, char *, int))
target_ignore);
+ de_fault (to_disconnect,
+ (void (*) (char *, int))
+ tcomplain);
de_fault (to_resume,
(void (*) (ptid_t, int, enum target_signal))
noprocess);
@@ -591,6 +594,7 @@ update_current_target (void)
INHERIT (to_require_attach, t);
INHERIT (to_detach, t);
INHERIT (to_require_detach, t);
+ INHERIT (to_disconnect, t);
INHERIT (to_resume, t);
INHERIT (to_wait, t);
INHERIT (to_post_wait, t);
@@ -1182,6 +1186,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"))
@@ -1654,6 +1668,15 @@ debug_to_require_detach (int pid, char *
}

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);
@@ -2397,6 +2420,7 @@ setup_target_debug (void)
current_target.to_require_attach = debug_to_require_attach;
current_target.to_detach = debug_to_detach;
current_target.to_require_detach = debug_to_require_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: target.h
===================================================================
RCS file: /cvs/src/src/gdb/target.h,v
retrieving revision 1.26
diff -u -p -r1.26 target.h
--- target.h 26 Aug 2002 19:18:33 -0000 1.26
+++ target.h 29 Aug 2002 19:38:41 -0000
@@ -196,6 +196,7 @@ struct target_ops
void (*to_require_attach) (char *, int);
void (*to_detach) (char *, int);
void (*to_require_detach) (int, 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);
@@ -435,6 +436,11 @@ extern void target_detach (char *, int);

#define target_require_detach(pid, args, from_tty) \
(*current_target.to_require_detach) (pid, args, from_tty)
+
+/* 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: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.115
diff -u -p -r1.115 gdb.texinfo
--- doc/gdb.texinfo 25 Aug 2002 19:10:15 -0000 1.115
+++ doc/gdb.texinfo 29 Aug 2002 19:38:46 -0000
@@ -10802,6 +10802,9 @@ step and continue the remote program.
To resume the remote program and stop debugging it, use the @code{detach}
command.

+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
@@ -14440,7 +14443,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: mi/gdbmi.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/mi/gdbmi.texinfo,v
retrieving revision 1.27
diff -u -p -r1.27 gdbmi.texinfo
--- mi/gdbmi.texinfo 17 Jun 2002 17:30:57 -0000 1.27
+++ mi/gdbmi.texinfo 29 Aug 2002 19:38:47 -0000
@@ -3109,6 +3109,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

Index: mi/mi-cmds.c
===================================================================
RCS file: /cvs/src/src/gdb/mi/mi-cmds.c,v
retrieving revision 1.8
diff -u -p -r1.8 mi-cmds.c
--- mi/mi-cmds.c 6 Mar 2001 08:21:45 -0000 1.8
+++ mi/mi-cmds.c 29 Aug 2002 19:38:47 -0000
@@ -122,6 +122,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},