diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e3293d15ea..edef298a6d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,69 @@ +2016-06-21 Pedro Alves + + * annotate.c: Include top.h. + (async_background_execution_p): Delete. + (print_value_flags): Check the UI's prompt state rather then + async_background_execution_p. + * event-loop.c (start_event_loop): Set the prompt state to + PROMPT_NEEDED. + * event-top.c (display_gdb_prompt, async_enable_stdin) + (async_disable_stdin): Check the current UI's prompt state instead + of the sync_execution global. + (command_line_handler): Set the prompt state to PROMPT_NEEDED + before running a command, and display the prompt if still needed + afterwards. + * infcall.c (struct call_thread_fsm) : New field. + (new_call_thread_fsm): New parameter 'waiting_ui'. Store it. + (call_thread_fsm_should_stop): Set the prompt state to + PROMPT_NEEDED. + (run_inferior_call): Adjust to temporarily set the prompt state to + PROMPT_BLOCKED instead of using the sync_execution global. + (call_function_by_hand_dummy): Pass the current UI to + new_call_thread_fsm. + * infcmd.c: Include top.h. + (continue_1): Check the current UI's prompt state instead of the + sync_execution global. + (continue_command): Validate global execution state before calling + prepare_execution_command. + (step_1): Call all_uis_check_sync_execution_done. + (attach_post_wait): Don't call async_enable_stdin here. Remove + reference to sync_execution. + * infrun.c (sync_execution): Delete global. + (follow_fork_inferior) + (reinstall_readline_callback_handler_cleanup): Check the current + UI's prompt state instead of the sync_execution global. + (check_curr_ui_sync_execution_done) + (all_uis_check_sync_execution_done): New functions. + (fetch_inferior_event): Call all_uis_check_sync_execution_done + instead of trying to determine whether the global sync execution + changed. + (handle_no_resumed): Check the prompt state of all UIs. + (normal_stop): Emit the no unwait-for even to all PROMPT_BLOCKED + UIs. Emit the "Switching to" notification to all UIs. Enable + stdin in all UIs. + * infrun.h (sync_execution): Delete. + (all_uis_check_sync_execution_done): Declare. + * main.c (captured_command_loop): Don't call + interp_pre_command_loop if the prompt is blocked. + (catch_command_errors, catch_command_errors_const): Adjust. + (captured_main): Set the initial prompt state to PROMPT_NEEDED. + * mi/mi-interp.c (display_mi_prompt): Set the prompt state to + PROMPTED. + (mi_interpreter_resume): Don't clear sync_execution. Remove hack + comment. + (mi_execute_command_input_handler): Set the prompt state to + PROMPT_NEEDED before executing the command, and only display the + prompt if the prompt state is PROMPT_NEEDED afterwards. + (mi_on_resume_1): Adjust to check the prompt state. + * target.c (target_terminal_inferior): Adjust to check the prompt + state. + * top.c (wait_sync_command_done, maybe_wait_sync_command_done) + (execute_command): Check the current UI's prompt state instead of + sync_execution. + * top.h (enum prompt_state): New. + (struct ui) : New field. + (ALL_UIS): New macro. + 2016-06-21 Pedro Alves * top.c (gdb_secondary_prompt_depth): Delete. diff --git a/gdb/annotate.c b/gdb/annotate.c index 117f12203b..64175a442b 100644 --- a/gdb/annotate.c +++ b/gdb/annotate.c @@ -25,6 +25,7 @@ #include "observer.h" #include "inferior.h" #include "infrun.h" +#include "top.h" /* Prototypes for local functions. */ @@ -46,16 +47,6 @@ void (*deprecated_annotate_signal_hook) (void); static int frames_invalid_emitted; static int breakpoints_invalid_emitted; -/* True if the target can async, and a synchronous execution command - is not in progress. If true, input is accepted, so don't suppress - annotations. */ - -static int -async_background_execution_p (void) -{ - return (target_can_async_p () && !sync_execution); -} - static void print_value_flags (struct type *t) { @@ -70,7 +61,7 @@ annotate_breakpoints_invalid (void) { if (annotation_level == 2 && (!breakpoints_invalid_emitted - || async_background_execution_p ())) + || current_ui->prompt_state != PROMPT_BLOCKED)) { /* If the inferior owns the terminal (e.g., we're resuming), make sure to leave with the inferior still owning it. */ @@ -217,7 +208,7 @@ annotate_frames_invalid (void) { if (annotation_level == 2 && (!frames_invalid_emitted - || async_background_execution_p ())) + || current_ui->prompt_state != PROMPT_BLOCKED)) { /* If the inferior owns the terminal (e.g., we're resuming), make sure to leave with the inferior still owning it. */ diff --git a/gdb/event-loop.c b/gdb/event-loop.c index fe28305050..f94a6fa135 100644 --- a/gdb/event-loop.c +++ b/gdb/event-loop.c @@ -381,6 +381,7 @@ start_event_loop (void) /* If we long-jumped out of do_one_event, we probably didn't get around to resetting the prompt, which leaves readline in a messed-up state. Reset it here. */ + current_ui->prompt_state = PROMPT_NEEDED; observer_notify_command_error (); /* This call looks bizarre, but it is required. If the user entered a command that caused an error, diff --git a/gdb/event-top.c b/gdb/event-top.c index 5e42c56051..c9e754875d 100644 --- a/gdb/event-top.c +++ b/gdb/event-top.c @@ -354,7 +354,11 @@ display_gdb_prompt (const char *new_prompt) IE, displayed but not set. */ if (! new_prompt) { - if (sync_execution) + struct ui *ui = current_ui; + + if (ui->prompt_state == PROMPTED) + internal_error (__FILE__, __LINE__, _("double prompt")); + else if (ui->prompt_state == PROMPT_BLOCKED) { /* This is to trick readline into not trying to display the prompt. Even though we display the prompt using this @@ -377,10 +381,11 @@ display_gdb_prompt (const char *new_prompt) do_cleanups (old_chain); return; } - else + else if (ui->prompt_state == PROMPT_NEEDED) { /* Display the top level prompt. */ actual_gdb_prompt = top_level_prompt (); + ui->prompt_state = PROMPTED; } } else @@ -541,14 +546,12 @@ stdin_event_handler (int error, gdb_client_data client_data) void async_enable_stdin (void) { - if (sync_execution) + struct ui *ui = current_ui; + + if (ui->prompt_state == PROMPT_BLOCKED) { - /* See NOTE in async_disable_stdin(). */ - /* FIXME: cagney/1999-09-27: Call this before clearing - sync_execution. Current target_terminal_ours() implementations - check for sync_execution before switching the terminal. */ target_terminal_ours (); - sync_execution = 0; + ui->prompt_state = PROMPT_NEEDED; } } @@ -558,7 +561,9 @@ async_enable_stdin (void) void async_disable_stdin (void) { - sync_execution = 1; + struct ui *ui = current_ui; + + ui->prompt_state = PROMPT_BLOCKED; } @@ -774,8 +779,12 @@ command_line_handler (char *rl) } else { + ui->prompt_state = PROMPT_NEEDED; + command_handler (cmd); - display_gdb_prompt (0); + + if (ui->prompt_state != PROMPTED) + display_gdb_prompt (0); } } diff --git a/gdb/infcall.c b/gdb/infcall.c index 11f5abacb5..d491f9526f 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -464,6 +464,10 @@ struct call_thread_fsm /* The called function's return value. This is extracted from the target before the dummy frame is popped. */ struct value *return_value; + + /* The top level that started the infcall (and is synchronously + waiting for it to end). */ + struct ui *waiting_ui; }; static int call_thread_fsm_should_stop (struct thread_fsm *self); @@ -484,7 +488,8 @@ static struct thread_fsm_ops call_thread_fsm_ops = /* Allocate a new call_thread_fsm object. */ static struct call_thread_fsm * -new_call_thread_fsm (struct gdbarch *gdbarch, struct value *function, +new_call_thread_fsm (struct ui *waiting_ui, + struct gdbarch *gdbarch, struct value *function, struct type *value_type, int struct_return_p, CORE_ADDR struct_addr) { @@ -499,6 +504,8 @@ new_call_thread_fsm (struct gdbarch *gdbarch, struct value *function, sm->return_meta_info.struct_return_p = struct_return_p; sm->return_meta_info.struct_addr = struct_addr; + sm->waiting_ui = waiting_ui; + return sm; } @@ -511,6 +518,8 @@ call_thread_fsm_should_stop (struct thread_fsm *self) if (stop_stack_dummy == STOP_STACK_DUMMY) { + struct cleanup *old_chain; + /* Done. */ thread_fsm_set_finished (self); @@ -520,7 +529,13 @@ call_thread_fsm_should_stop (struct thread_fsm *self) f->return_value = get_call_return_value (&f->return_meta_info); /* Break out of wait_sync_command_done. */ - async_enable_stdin (); + old_chain = make_cleanup (restore_ui_cleanup, current_ui); + current_ui = f->waiting_ui; + target_terminal_ours (); + f->waiting_ui->prompt_state = PROMPT_NEEDED; + + /* This restores the previous UI. */ + do_cleanups (old_chain); } return 1; @@ -558,12 +573,12 @@ run_inferior_call (struct call_thread_fsm *sm, struct gdb_exception caught_error = exception_none; int saved_in_infcall = call_thread->control.in_infcall; ptid_t call_thread_ptid = call_thread->ptid; - int saved_sync_execution = sync_execution; + enum prompt_state saved_prompt_state = current_ui->prompt_state; int was_running = call_thread->state == THREAD_RUNNING; int saved_ui_async = current_ui->async; /* Infcalls run synchronously, in the foreground. */ - sync_execution = 1; + current_ui->prompt_state = PROMPT_BLOCKED; /* So that we don't print the prompt prematurely in fetch_inferior_event. */ current_ui->async = 0; @@ -596,11 +611,11 @@ run_inferior_call (struct call_thread_fsm *sm, } END_CATCH - /* If GDB was previously in sync execution mode, then ensure that it - remains so. normal_stop calls async_enable_stdin, so reset it - again here. In other cases, stdin will be re-enabled by + /* If GDB has the prompt blocked before, then ensure that it remains + so. normal_stop calls async_enable_stdin, so reset the prompt + state again here. In other cases, stdin will be re-enabled by inferior_event_handler, when an exception is thrown. */ - sync_execution = saved_sync_execution; + current_ui->prompt_state = saved_prompt_state; current_ui->async = saved_ui_async; /* At this point the current thread may have changed. Refresh @@ -1120,7 +1135,8 @@ call_function_by_hand_dummy (struct value *function, not report the stop to the user, and captures the return value before the dummy frame is popped. run_inferior_call registers it with the thread ASAP. */ - sm = new_call_thread_fsm (gdbarch, function, + sm = new_call_thread_fsm (current_ui, + gdbarch, function, values_type, struct_return || hidden_first_param_p, struct_addr); diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 1defb13806..5c3f212bfe 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -56,6 +56,7 @@ #include "cli/cli-utils.h" #include "infcall.h" #include "thread-fsm.h" +#include "top.h" /* Local functions: */ @@ -730,7 +731,7 @@ continue_1 (int all_threads) iterate_over_threads (proceed_thread_callback, NULL); - if (sync_execution) + if (current_ui->prompt_state == PROMPT_BLOCKED) { /* If all threads in the target were already running, proceed_thread_callback ends up never calling proceed, @@ -775,8 +776,6 @@ continue_command (char *args, int from_tty) args = strip_bg_char (args, &async_exec); args_chain = make_cleanup (xfree, args); - prepare_execution_command (¤t_target, async_exec); - if (args != NULL) { if (startswith (args, "-a")) @@ -840,6 +839,17 @@ continue_command (char *args, int from_tty) /* Done with ARGS. */ do_cleanups (args_chain); + ERROR_NO_INFERIOR; + ensure_not_tfind_mode (); + + if (!non_stop || !all_threads) + { + ensure_valid_thread (); + ensure_not_running (); + } + + prepare_execution_command (¤t_target, async_exec); + if (from_tty) printf_filtered (_("Continuing.\n")); @@ -1014,11 +1024,15 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); else { + int proceeded; + /* Stepped into an inline frame. Pretend that we've stopped. */ thread_fsm_clean_up (thr->thread_fsm); - normal_stop (); - inferior_event_handler (INF_EXEC_COMPLETE, NULL); + proceeded = normal_stop (); + if (!proceeded) + inferior_event_handler (INF_EXEC_COMPLETE, NULL); + all_uis_check_sync_execution_done (); } } @@ -2710,8 +2724,6 @@ attach_post_wait (char *args, int from_tty, enum attach_post_wait_mode mode) /* The user requested a plain `attach', so be sure to leave the inferior stopped. */ - async_enable_stdin (); - /* At least the current thread is already stopped. */ /* In all-stop, by definition, all threads have to be already @@ -2885,7 +2897,7 @@ attach_command (char *args, int from_tty) STOP_QUIETLY_NO_SIGSTOP is for. */ inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP; - /* sync_execution mode. Wait for stop. */ + /* Wait for stop. */ a = XNEW (struct attach_command_continuation_args); a->args = xstrdup (args); a->from_tty = from_tty; diff --git a/gdb/infrun.c b/gdb/infrun.c index 1e9c28ef4f..25313b476a 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -152,10 +152,6 @@ show_step_stop_if_no_debug (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Mode of the step operation is %s.\n"), value); } -/* In asynchronous mode, but simulating synchronous execution. */ - -int sync_execution = 0; - /* proceed and normal_stop use this to notify the user when the inferior stopped in a different thread than it had been running in. */ @@ -442,7 +438,7 @@ follow_fork_inferior (int follow_child, int detach_fork) if (has_vforked && !non_stop /* Non-stop always resumes both branches. */ - && (!target_is_async_p () || sync_execution) + && current_ui->prompt_state == PROMPT_BLOCKED && !(follow_child || detach_fork || sched_multi)) { /* The parent stays blocked inside the vfork syscall until the @@ -3802,7 +3798,9 @@ wait_for_inferior (void) static void reinstall_readline_callback_handler_cleanup (void *arg) { - if (!current_ui->async) + struct ui *ui = current_ui; + + if (!ui->async) { /* We're not going back to the top level event loop yet. Don't install the readline callback, as it'd prep the terminal, @@ -3812,7 +3810,7 @@ reinstall_readline_callback_handler_cleanup (void *arg) return; } - if (current_ui->command_editing && !sync_execution) + if (ui->command_editing && ui->prompt_state != PROMPT_BLOCKED) gdb_rl_callback_handler_reinstall (); } @@ -3845,6 +3843,36 @@ clean_up_just_stopped_threads_fsms (struct execution_control_state *ecs) } } +/* Helper for all_uis_check_sync_execution_done that works on the + current UI. */ + +static void +check_curr_ui_sync_execution_done (void) +{ + struct ui *ui = current_ui; + + if (ui->prompt_state == PROMPT_NEEDED + && ui->async + && !gdb_in_secondary_prompt_p (ui)) + { + target_terminal_ours (); + observer_notify_sync_execution_done (); + } +} + +/* See infrun.h. */ + +void +all_uis_check_sync_execution_done (void) +{ + struct switch_thru_all_uis state; + + SWITCH_THRU_ALL_UIS (state) + { + check_curr_ui_sync_execution_done (); + } +} + /* A cleanup that restores the execution direction to the value saved in *ARG. */ @@ -3872,7 +3900,6 @@ fetch_inferior_event (void *client_data) struct execution_control_state *ecs = &ecss; struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); struct cleanup *ts_old_chain; - int was_sync = sync_execution; enum exec_direction_kind save_exec_dir = execution_direction; int cmd_done = 0; ptid_t waiton_ptid = minus_one_ptid; @@ -3992,14 +4019,12 @@ fetch_inferior_event (void *client_data) /* Revert thread and frame. */ do_cleanups (old_chain); - /* If the inferior was in sync execution mode, and now isn't, - restore the prompt (a synchronous execution command has finished, - and we're ready for input). */ - if (current_ui->async && was_sync && !sync_execution) - observer_notify_sync_execution_done (); + /* If a UI was in sync execution mode, and now isn't, restore its + prompt (a synchronous execution command has finished, and we're + ready for input). */ + all_uis_check_sync_execution_done (); if (cmd_done - && !was_sync && exec_done_display_p && (ptid_equal (inferior_ptid, null_ptid) || !is_running (inferior_ptid))) @@ -4685,17 +4710,32 @@ handle_no_resumed (struct execution_control_state *ecs) struct inferior *inf; struct thread_info *thread; - if (target_can_async_p () && !sync_execution) + if (target_can_async_p ()) { - /* There were no unwaited-for children left in the target, but, - we're not synchronously waiting for events either. Just - ignore. */ + struct ui *ui; + int any_sync = 0; - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, - "infrun: TARGET_WAITKIND_NO_RESUMED " "(ignoring: bg)\n"); - prepare_to_wait (ecs); - return 1; + ALL_UIS (ui) + { + if (ui->prompt_state == PROMPT_BLOCKED) + { + any_sync = 1; + break; + } + } + if (!any_sync) + { + /* There were no unwaited-for children left in the target, but, + we're not synchronously waiting for events either. Just + ignore. */ + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: TARGET_WAITKIND_NO_RESUMED " + "(ignoring: bg)\n"); + prepare_to_wait (ecs); + return 1; + } } /* Otherwise, if we were running a synchronous execution command, we @@ -8194,6 +8234,7 @@ normal_stop (void) ptid_t last_ptid; struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); ptid_t pid_ptid; + struct switch_thru_all_uis state; get_last_target_status (&last_ptid, &last); @@ -8258,19 +8299,24 @@ normal_stop (void) && last.kind != TARGET_WAITKIND_EXITED && last.kind != TARGET_WAITKIND_NO_RESUMED) { - target_terminal_ours_for_output (); - printf_filtered (_("[Switching to %s]\n"), - target_pid_to_str (inferior_ptid)); - annotate_thread_changed (); + SWITCH_THRU_ALL_UIS (state) + { + target_terminal_ours_for_output (); + printf_filtered (_("[Switching to %s]\n"), + target_pid_to_str (inferior_ptid)); + annotate_thread_changed (); + } previous_inferior_ptid = inferior_ptid; } if (last.kind == TARGET_WAITKIND_NO_RESUMED) { - gdb_assert (sync_execution || !target_can_async_p ()); - - target_terminal_ours_for_output (); - printf_filtered (_("No unwaited-for children left.\n")); + SWITCH_THRU_ALL_UIS (state) + if (current_ui->prompt_state == PROMPT_BLOCKED) + { + target_terminal_ours_for_output (); + printf_filtered (_("No unwaited-for children left.\n")); + } } /* Note: this depends on the update_thread_list call above. */ @@ -8282,8 +8328,10 @@ normal_stop (void) if (stopped_by_random_signal) disable_current_display (); - target_terminal_ours (); - async_enable_stdin (); + SWITCH_THRU_ALL_UIS (state) + { + async_enable_stdin (); + } /* Let the user/frontend see the threads as stopped. */ do_cleanups (old_chain); diff --git a/gdb/infrun.h b/gdb/infrun.h index e79bf2d83d..01eff9a1db 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -35,11 +35,6 @@ extern int debug_displaced; of shared library events by the dynamic linker. */ extern int stop_on_solib_events; -/* Are we simulating synchronous execution? This is used in async gdb - to implement the 'run', 'continue' etc commands, which will not - redisplay the prompt until the execution is actually over. */ -extern int sync_execution; - /* True if execution commands resume all threads of all processes by default; otherwise, resume only threads of the current inferior process. */ @@ -238,4 +233,9 @@ extern struct thread_info *step_over_queue_head; is stopped). On failure, print a message. */ extern void maybe_remove_breakpoints (void); +/* If a UI was in sync execution mode, and now isn't, restore its + prompt (a synchronous execution command has finished, and we're + ready for input). */ +extern void all_uis_check_sync_execution_done (void); + #endif /* INFRUN_H */ diff --git a/gdb/main.c b/gdb/main.c index a1ce327641..c45bffd81e 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -315,8 +315,9 @@ captured_command_loop (void *data) here on. */ current_ui->async = 1; - /* Give the interpreter a chance to print a prompt. */ - interp_pre_command_loop (top_level_interpreter ()); + /* Give the interpreter a chance to print a prompt, if necessary */ + if (ui->prompt_state != PROMPT_BLOCKED) + interp_pre_command_loop (top_level_interpreter ()); /* Now it's time to start the event loop. */ start_event_loop (); @@ -368,7 +369,7 @@ catch_command_errors (catch_command_errors_ftype *command, { TRY { - int was_sync = sync_execution; + int was_sync = current_ui->prompt_state == PROMPT_BLOCKED; command (arg, from_tty); @@ -395,7 +396,7 @@ catch_command_errors_const (catch_command_errors_const_ftype *command, { TRY { - int was_sync = sync_execution; + int was_sync = current_ui->prompt_state == PROMPT_BLOCKED; command (arg, from_tty); @@ -519,6 +520,8 @@ captured_main (void *data) ui->input_fd = fileno (stdin); + ui->prompt_state = PROMPT_NEEDED; + #ifdef __MINGW32__ /* Ensure stderr is unbuffered. A Cygwin pty or pipe is implemented as a Windows pipe, and Windows buffers on pipes. */ diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 4376ffa06a..5db61e14f1 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -93,8 +93,11 @@ static int report_initial_inferior (struct inferior *inf, void *closure); static void display_mi_prompt (struct mi_interp *mi) { + struct ui *ui = current_ui; + fputs_unfiltered ("(gdb) \n", mi->raw_stdout); gdb_flush (mi->raw_stdout); + ui->prompt_state = PROMPTED; } /* Returns the INTERP's data cast as mi_interp if INTERP is an MI, and @@ -169,13 +172,6 @@ mi_interpreter_resume (void *data) ui->call_readline = gdb_readline_no_editing_callback; ui->input_handler = mi_execute_command_input_handler; - /* FIXME: This is a total hack for now. PB's use of the MI - implicitly relies on a bug in the async support which allows - asynchronous commands to leak through the commmand loop. The bug - involves (but is not limited to) the fact that sync_execution was - erroneously initialized to 0. Duplicate by initializing it thus - here... */ - sync_execution = 0; gdb_stdout = mi->out; /* Route error and log output through the MI. */ @@ -315,6 +311,9 @@ static void mi_execute_command_input_handler (char *cmd) { struct mi_interp *mi = as_mi_interp (top_level_interpreter ()); + struct ui *ui = current_ui; + + ui->prompt_state = PROMPT_NEEDED; mi_execute_command_wrapper (cmd); @@ -323,7 +322,7 @@ mi_execute_command_input_handler (char *cmd) to go back to the event loop and will output the prompt in the 'synchronous_command_done' observer when the target next stops. */ - if (!sync_execution) + if (ui->prompt_state == PROMPT_NEEDED) display_mi_prompt (mi); } @@ -1139,12 +1138,10 @@ mi_on_resume_1 (struct mi_interp *mi, ptid_t ptid) if (!running_result_record_printed && mi_proceeded) { running_result_record_printed = 1; - /* This is what gdb used to do historically -- printing prompt even if - it cannot actually accept any input. This will be surely removed - for MI3, and may be removed even earlier. SYNC_EXECUTION is - checked here because we only need to emit a prompt if a - synchronous command was issued when the target is async. */ - if (!target_can_async_p () || sync_execution) + /* This is what gdb used to do historically -- printing prompt + even if it cannot actually accept any input. This will be + surely removed for MI3, and may be removed even earlier. */ + if (current_ui->prompt_state == PROMPT_BLOCKED) fputs_unfiltered ("(gdb) \n", mi->raw_stdout); } gdb_flush (mi->raw_stdout); diff --git a/gdb/target.c b/gdb/target.c index 8a83fbac70..6f69ac37a1 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -482,10 +482,8 @@ target_terminal_inferior (void) struct ui *ui = current_ui; /* A background resume (``run&'') should leave GDB in control of the - terminal. Use target_can_async_p, not target_is_async_p, since at - this point the target is not async yet. However, if sync_execution - is not set, we know it will become async prior to resume. */ - if (target_can_async_p () && !sync_execution) + terminal. */ + if (ui->prompt_state != PROMPT_BLOCKED) return; /* Always delete the current UI's input file handler, regardless of diff --git a/gdb/top.c b/gdb/top.c index 79f4293556..e40835b7e7 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -391,7 +391,7 @@ void wait_sync_command_done (void) { while (gdb_do_one_event () >= 0) - if (!sync_execution) + if (current_ui->prompt_state != PROMPT_BLOCKED) break; } @@ -404,7 +404,9 @@ maybe_wait_sync_command_done (int was_sync) command's list, running command hooks or similars), and we just ran a synchronous command that started the target, wait for that command to end. */ - if (!current_ui->async && !was_sync && sync_execution) + if (!current_ui->async + && !was_sync + && current_ui->prompt_state == PROMPT_BLOCKED) wait_sync_command_done (); } @@ -441,7 +443,7 @@ execute_command (char *p, int from_tty) { const char *cmd = p; char *arg; - int was_sync = sync_execution; + int was_sync = current_ui->prompt_state == PROMPT_BLOCKED; line = p; diff --git a/gdb/top.h b/gdb/top.h index 2aa44080c9..df96baa167 100644 --- a/gdb/top.h +++ b/gdb/top.h @@ -25,6 +25,24 @@ struct tl_interp_info; +/* Prompt state. */ + +enum prompt_state +{ + /* The command line is blocked simulating synchronous execution. + This is used to implement the foreground execution commands + ('run', 'continue', etc.). We won't display the prompt and + accept further commands until the execution is actually over. */ + PROMPT_BLOCKED, + + /* The command finished; display the prompt before returning back to + the top level. */ + PROMPT_NEEDED, + + /* We've displayed the prompt already, ready for input. */ + PROMPTED, +}; + /* All about a user interface instance. Each user interface has its own I/O files/streams, readline state, its own top level interpreter (for the main UI, this is the interpreter specified @@ -91,6 +109,9 @@ struct ui it with the event loop. */ int input_fd; + /* See enum prompt_state's description. */ + enum prompt_state prompt_state; + /* The fields below that start with "m_" are "private". They're meant to be accessed through wrapper macros that make them look like globals. */ @@ -145,6 +166,10 @@ extern void switch_thru_all_uis_next (struct switch_thru_all_uis *state); switch_thru_all_uis_cond (&STATE); \ switch_thru_all_uis_next (&STATE)) +/* Traverse over all UIs. */ +#define ALL_UIS(UI) \ + for (UI = ui_list; UI; UI = UI->next) \ + /* Cleanup that restores the current UI. */ extern void restore_ui_cleanup (void *data);