aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog66
-rw-r--r--gdb/annotate.c15
-rw-r--r--gdb/event-loop.c1
-rw-r--r--gdb/event-top.c29
-rw-r--r--gdb/infcall.c34
-rw-r--r--gdb/infcmd.c28
-rw-r--r--gdb/infrun.c114
-rw-r--r--gdb/infrun.h10
-rw-r--r--gdb/main.c11
-rw-r--r--gdb/mi/mi-interp.c25
-rw-r--r--gdb/target.c6
-rw-r--r--gdb/top.c8
-rw-r--r--gdb/top.h25
13 files changed, 270 insertions, 102 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index e3293d1..edef298 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,71 @@
2016-06-21 Pedro Alves <palves@redhat.com>
+ * 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) <waiting_ui>: 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) <prompt_state>: New field.
+ (ALL_UIS): New macro.
+
+2016-06-21 Pedro Alves <palves@redhat.com>
+
* top.c (gdb_secondary_prompt_depth): Delete.
(gdb_in_secondary_prompt_p): Add ui parameter. Use it.
(gdb_readline_wrapper_cleanup, gdb_readline_wrapper): Adjust to
diff --git a/gdb/annotate.c b/gdb/annotate.c
index 117f122..64175a4 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 fe28305..f94a6fa 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 5e42c560..c9e7548 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 11f5aba..d491f95 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 1defb13..5c3f212 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 (&current_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 (&current_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 1e9c28e..25313b4 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 e79bf2d..01eff9a 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 a1ce327..c45bffd 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 4376ffa..5db61e1 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 8a83fba..6f69ac3 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 79f4293..e40835b 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 2aa4408..df96baa 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);