diff options
author | Pedro Alves <palves@redhat.com> | 2014-10-17 13:31:26 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2014-10-17 13:34:16 +0100 |
commit | 6c4486e63f7583ed85a0c72841f6ccceebbf858e (patch) | |
tree | 02307265129b92c560eea444a06f25d409959bf7 /gdb/infcmd.c | |
parent | 0ff33695eeedf3c2e8cdec8690ae4a10a66b3389 (diff) | |
download | gdb-6c4486e63f7583ed85a0c72841f6ccceebbf858e.zip gdb-6c4486e63f7583ed85a0c72841f6ccceebbf858e.tar.gz gdb-6c4486e63f7583ed85a0c72841f6ccceebbf858e.tar.bz2 |
PR gdb/17471: Repeating a background command makes it foreground
When we repeat a command, by just pressing <ret>, the input from the
previous command is reused for the new command invocation.
When an execution command strips the "&" out of its incoming argument
string, to detect background execution, we poke a '\0' directly to the
incoming argument string.
Combine both, and a repeat of a background command loses the "&".
This is actually only visible if args other than "&" are specified
(e.g., "c 1&" or "next 2&" or "c -a&"), as in the special case of "&"
alone (e.g. "c&") doesn't actually clobber the incoming string.
Fix this by making strip_bg_char return a new string instead of poking
a hole in the input string.
New test included.
Tested on x86_64 Fedora 20, native and gdbserver.
gdb/
2014-10-17 Pedro Alves <palves@redhat.com>
PR gdb/17471
* infcmd.c (strip_bg_char): Change prototype and rewrite. Now
returns a copy of the input.
(run_command_1, continue_command, step_1, jump_command)
(signal_command, until_command, advance_command, finish_command)
(attach_command): Adjust and install a cleanup to free the
stripped args.
gdb/testsuite/
2014-10-17 Pedro Alves <palves@redhat.com>
PR gdb/17471
* gdb.base/bg-execution-repeat.c: New file.
* gdb.base/bg-execution-repeat.exp: New file.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r-- | gdb/infcmd.c | 142 |
1 files changed, 89 insertions, 53 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c index d270664..4415b31 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -104,8 +104,6 @@ static void run_no_args_command (char *args, int from_tty); static void go_command (char *line_no, int from_tty); -static int strip_bg_char (char **); - void _initialize_infcmd (void); #define ERROR_NO_INFERIOR \ @@ -370,35 +368,40 @@ construct_inferior_arguments (int argc, char **argv) } -/* This function detects whether or not a '&' character (indicating - background execution) has been added as *the last* of the arguments ARGS - of a command. If it has, it removes it and returns 1. Otherwise it - does nothing and returns 0. */ +/* This function strips the '&' character (indicating background + execution) that is added as *the last* of the arguments ARGS of a + command. A copy of the incoming ARGS without the '&' is returned, + unless the resulting string after stripping is empty, in which case + NULL is returned. *BG_CHAR_P is an output boolean that indicates + whether the '&' character was found. */ -static int -strip_bg_char (char **args) +static char * +strip_bg_char (const char *args, int *bg_char_p) { - char *p = NULL; + const char *p; - p = strchr (*args, '&'); + if (args == NULL || *args == '\0') + { + *bg_char_p = 0; + return NULL; + } - if (p) + p = args + strlen (args); + if (p[-1] == '&') { - if (p == (*args + strlen (*args) - 1)) - { - if (strlen (*args) > 1) - { - do - p--; - while (*p == ' ' || *p == '\t'); - *(p + 1) = '\0'; - } - else - *args = 0; - return 1; - } + p--; + while (p > args && isspace (p[-1])) + p--; + + *bg_char_p = 1; + if (p != args) + return savestring (args, p - args); + else + return NULL; } - return 0; + + *bg_char_p = 0; + return xstrdup (args); } /* Common actions to take after creating any sort of inferior, by any @@ -527,7 +530,8 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) ptid_t ptid; struct ui_out *uiout = current_uiout; struct target_ops *run_target; - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; dont_repeat (); @@ -550,8 +554,8 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) reopen_exec_file (); reread_symbols (); - if (args != NULL) - async_exec = strip_bg_char (&args); + args = strip_bg_char (args, &async_exec); + args_chain = make_cleanup (xfree, args); /* Do validation and preparation before possibly changing anything in the inferior. */ @@ -597,6 +601,9 @@ run_command_1 (char *args, int from_tty, int tbreak_at_main) ui_out_flush (uiout); } + /* Done with ARGS. */ + do_cleanups (args_chain); + /* We call get_inferior_args() because we might need to compute the value now. */ run_target->to_create_inferior (run_target, exec_file, get_inferior_args (), @@ -770,13 +777,15 @@ continue_1 (int all_threads) static void continue_command (char *args, int from_tty) { - int async_exec = 0; + int async_exec; int all_threads = 0; + struct cleanup *args_chain; + ERROR_NO_INFERIOR; /* Find out whether we must run in the background. */ - if (args != NULL) - async_exec = strip_bg_char (&args); + args = strip_bg_char (args, &async_exec); + args_chain = make_cleanup (xfree, args); prepare_execution_command (¤t_target, async_exec); @@ -840,6 +849,9 @@ continue_command (char *args, int from_tty) } } + /* Done with ARGS. */ + do_cleanups (args_chain); + if (from_tty) printf_filtered (_("Continuing.\n")); @@ -899,21 +911,25 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) { int count = 1; struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); - int async_exec = 0; + int async_exec; int thread = -1; + struct cleanup *args_chain; ERROR_NO_INFERIOR; ensure_not_tfind_mode (); ensure_valid_thread (); ensure_not_running (); - if (count_string) - async_exec = strip_bg_char (&count_string); + count_string = strip_bg_char (count_string, &async_exec); + args_chain = make_cleanup (xfree, count_string); prepare_execution_command (¤t_target, async_exec); count = count_string ? parse_and_eval_long (count_string) : 1; + /* Done with ARGS. */ + do_cleanups (args_chain); + if (!single_inst || skip_subroutines) /* Leave si command alone. */ { struct thread_info *tp = inferior_thread (); @@ -1134,7 +1150,8 @@ jump_command (char *arg, int from_tty) struct symtab_and_line sal; struct symbol *fn; struct symbol *sfn; - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; ERROR_NO_INFERIOR; ensure_not_tfind_mode (); @@ -1142,8 +1159,8 @@ jump_command (char *arg, int from_tty) ensure_not_running (); /* Find out whether we must run in the background. */ - if (arg != NULL) - async_exec = strip_bg_char (&arg); + arg = strip_bg_char (arg, &async_exec); + args_chain = make_cleanup (xfree, arg); prepare_execution_command (¤t_target, async_exec); @@ -1159,6 +1176,9 @@ jump_command (char *arg, int from_tty) sal = sals.sals[0]; xfree (sals.sals); + /* Done with ARGS. */ + do_cleanups (args_chain); + if (sal.symtab == 0 && sal.pc == 0) error (_("No source file has been specified.")); @@ -1227,7 +1247,8 @@ static void signal_command (char *signum_exp, int from_tty) { enum gdb_signal oursig; - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; dont_repeat (); /* Too dangerous. */ ERROR_NO_INFERIOR; @@ -1236,8 +1257,8 @@ signal_command (char *signum_exp, int from_tty) ensure_not_running (); /* Find out whether we must run in the background. */ - if (signum_exp != NULL) - async_exec = strip_bg_char (&signum_exp); + signum_exp = strip_bg_char (signum_exp, &async_exec); + args_chain = make_cleanup (xfree, signum_exp); prepare_execution_command (¤t_target, async_exec); @@ -1453,7 +1474,8 @@ until_next_command (int from_tty) static void until_command (char *arg, int from_tty) { - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; ERROR_NO_INFERIOR; ensure_not_tfind_mode (); @@ -1461,8 +1483,8 @@ until_command (char *arg, int from_tty) ensure_not_running (); /* Find out whether we must run in the background. */ - if (arg != NULL) - async_exec = strip_bg_char (&arg); + arg = strip_bg_char (arg, &async_exec); + args_chain = make_cleanup (xfree, arg); prepare_execution_command (¤t_target, async_exec); @@ -1470,12 +1492,16 @@ until_command (char *arg, int from_tty) until_break_command (arg, from_tty, 0); else until_next_command (from_tty); + + /* Done with ARGS. */ + do_cleanups (args_chain); } static void advance_command (char *arg, int from_tty) { - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; ERROR_NO_INFERIOR; ensure_not_tfind_mode (); @@ -1486,12 +1512,15 @@ advance_command (char *arg, int from_tty) error_no_arg (_("a location")); /* Find out whether we must run in the background. */ - if (arg != NULL) - async_exec = strip_bg_char (&arg); + arg = strip_bg_char (arg, &async_exec); + args_chain = make_cleanup (xfree, arg); prepare_execution_command (¤t_target, async_exec); until_break_command (arg, from_tty, 1); + + /* Done with ARGS. */ + do_cleanups (args_chain); } /* Return the value of the result of a function at the end of a 'finish' @@ -1766,8 +1795,8 @@ finish_command (char *arg, int from_tty) { struct frame_info *frame; struct symbol *function; - - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; ERROR_NO_INFERIOR; ensure_not_tfind_mode (); @@ -1775,14 +1804,17 @@ finish_command (char *arg, int from_tty) ensure_not_running (); /* Find out whether we must run in the background. */ - if (arg != NULL) - async_exec = strip_bg_char (&arg); + arg = strip_bg_char (arg, &async_exec); + args_chain = make_cleanup (xfree, arg); prepare_execution_command (¤t_target, async_exec); if (arg) error (_("The \"finish\" command does not take any arguments.")); + /* Done with ARGS. */ + do_cleanups (args_chain); + frame = get_prev_frame (get_selected_frame (_("No selected frame."))); if (frame == 0) error (_("\"finish\" not meaningful in the outermost frame.")); @@ -2546,7 +2578,8 @@ attach_command_continuation_free_args (void *args) void attach_command (char *args, int from_tty) { - int async_exec = 0; + int async_exec; + struct cleanup *args_chain; struct target_ops *attach_target; dont_repeat (); /* Not for the faint of heart */ @@ -2567,8 +2600,8 @@ attach_command (char *args, int from_tty) this function should probably be moved into target_pre_inferior. */ target_pre_inferior (from_tty); - if (args != NULL) - async_exec = strip_bg_char (&args); + args = strip_bg_char (args, &async_exec); + args_chain = make_cleanup (xfree, args); attach_target = find_attach_target (); @@ -2582,6 +2615,9 @@ attach_command (char *args, int from_tty) shouldn't refer to attach_target again. */ attach_target = NULL; + /* Done with ARGS. */ + do_cleanups (args_chain); + /* Set up the "saved terminal modes" of the inferior based on what modes we are starting it with. */ target_terminal_init (); |