New command queue-signal.

If I want to change the signalled state of multiple threads
it's a bit cumbersome to do with the "signal" command.
What you really want is a way to set the signal state of the
desired threads and then just do "continue".

This patch adds a new command, queue-signal, to accomplish this.
Basically "signal N" == "queue-signal N" + "continue".
That's not precisely true in that "signal" can be used to inject
any signal, including signals set to "nopass"; whereas "queue-signal"
just queues the signal as if the thread stopped because of it.
"nopass" handling is done when the thread is resumed which
"queue-signal" doesn't do.

One could add extra complexity to allow queue-signal to be used to
deliver "nopass" signals like the "signal" command.  I have no current
need for it so in the interests of incremental complexity, I have
left such support out and just have the code flag an error if one
tries to queue a nopass signal.

gdb/ChangeLog:

	* NEWS: Mention new "queue-signal" command.
	* infcmd.c (queue_signal_command): New function.
	(_initialize_infcmd): Add new queue-signal command.

gdb/doc/ChangeLog:

	* gdb.texinfo (Signaling): Document new queue-signal command.

gdb/testsuite/ChangeLog:

	* gdb.threads/queue-signal.c: New file.
	* gdb.threads/queue-signal.exp: New file.
This commit is contained in:
Doug Evans
2014-09-13 21:44:00 -07:00
parent d4b38d2d05
commit 81219e5358
8 changed files with 297 additions and 6 deletions

View File

@@ -1300,6 +1300,46 @@ signal_command (char *signum_exp, int from_tty)
proceed ((CORE_ADDR) -1, oursig, 0);
}
/* Queue a signal to be delivered to the current thread. */
static void
queue_signal_command (char *signum_exp, int from_tty)
{
enum gdb_signal oursig;
struct thread_info *tp;
ERROR_NO_INFERIOR;
ensure_not_tfind_mode ();
ensure_valid_thread ();
ensure_not_running ();
if (signum_exp == NULL)
error_no_arg (_("signal number"));
/* It would be even slicker to make signal names be valid expressions,
(the type could be "enum $signal" or some such), then the user could
assign them to convenience variables. */
oursig = gdb_signal_from_name (signum_exp);
if (oursig == GDB_SIGNAL_UNKNOWN)
{
/* No, try numeric. */
int num = parse_and_eval_long (signum_exp);
if (num == 0)
oursig = GDB_SIGNAL_0;
else
oursig = gdb_signal_from_command (num);
}
if (oursig != GDB_SIGNAL_0
&& !signal_pass_state (oursig))
error (_("Signal handling set to not pass this signal to the program."));
tp = inferior_thread ();
tp->suspend.stop_signal = oursig;
}
/* Continuation args to be passed to the "until" command
continuation. */
struct until_next_continuation_args
@@ -3008,7 +3048,24 @@ The SIGNAL argument is processed the same as the handle command.\n\
\n\
An argument of \"0\" means continue the program without sending it a signal.\n\
This is useful in cases where the program stopped because of a signal,\n\
and you want to resume the program while discarding the signal."));
and you want to resume the program while discarding the signal.\n\
\n\
In a multi-threaded program the signal is delivered to, or discarded from,\n\
the current thread only."));
set_cmd_completer (c, signal_completer);
c = add_com ("queue-signal", class_run, queue_signal_command, _("\
Queue a signal to be delivered to the current thread when it is resumed.\n\
Usage: queue-signal SIGNAL\n\
The SIGNAL argument is processed the same as the handle command.\n\
It is an error if the handling state of SIGNAL is \"nopass\".\n\
\n\
An argument of \"0\" means remove any currently queued signal from\n\
the current thread. This is useful in cases where the program stopped\n\
because of a signal, and you want to resume it while discarding the signal.\n\
\n\
In a multi-threaded program the signal is queued with, or discarded from,\n\
the current thread only."));
set_cmd_completer (c, signal_completer);
add_com ("stepi", class_run, stepi_command, _("\