diff options
-rw-r--r-- | gdb/ChangeLog | 45 | ||||
-rw-r--r-- | gdb/breakpoint.c | 4 | ||||
-rw-r--r-- | gdb/inf-loop.c | 2 | ||||
-rw-r--r-- | gdb/infcall.c | 36 | ||||
-rw-r--r-- | gdb/infcmd.c | 143 | ||||
-rw-r--r-- | gdb/infrun.c | 37 | ||||
-rw-r--r-- | gdb/infrun.h | 4 | ||||
-rw-r--r-- | gdb/linux-nat.c | 23 | ||||
-rw-r--r-- | gdb/mi/mi-interp.c | 32 | ||||
-rw-r--r-- | gdb/target-delegates.c | 8 | ||||
-rw-r--r-- | gdb/target.c | 11 | ||||
-rw-r--r-- | gdb/target.h | 9 | ||||
-rw-r--r-- | gdb/top.c | 16 | ||||
-rw-r--r-- | gdb/top.h | 3 |
14 files changed, 174 insertions, 199 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bed048a..e4a13bb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,48 @@ +2015-09-09 Pedro Alves <palves@redhat.com> + + * breakpoint.c (bpstat_do_actions_1, until_break_command): Don't + check whether the target can async. + * inf-loop.c (inferior_event_handler): Only call target_async if + the target can async. + * infcall.c: Include top.h and interps.h. + (run_inferior_call): For the interpreter to sync mode while + running the infcall. Call wait_sync_command_done instead of + wait_for_inferior plus normal_stop. + * infcmd.c (prepare_execution_command): Don't check whether the + target can async when running in the foreground. + (step_1): Delete synchronous case handling. + (step_once): Always install a continuation, even in sync mode. + (until_next_command, finish_forward): Don't check whether the + target can async. + (attach_command_post_wait, notice_new_inferior): Always install a + continuation, even in sync mode. + * infrun.c (mark_infrun_async_event_handler): New function. + (proceed): In sync mode, mark infrun's event source instead of + waiting for events here. + (fetch_inferior_event): If the target can't async, do a blocking + wait. + (prepare_to_wait): In sync mode, mark infrun's event source. + (infrun_async_inferior_event_handler): No longer bail out if the + target can't async. + * infrun.h (mark_infrun_async_event_handler): New declaration. + * linux-nat.c (linux_nat_wait_1): Remove calls to + set_sigint_trap/clear_sigint_trap. + (linux_nat_terminal_inferior): No longer check whether the target + can async. + * mi/mi-interp.c (mi_on_sync_execution_done): Update and simplify + comment. + (mi_execute_command_input_handler): No longer check whether the + target is async. Update and simplify comment. + * target.c (default_target_wait): New function. + * target.h (struct target_ops) <to_wait>: Now defaults to + default_target_wait. + (default_target_wait): Declare. + * top.c (wait_sync_command_done): New function, factored out from + ... + (maybe_wait_sync_command_done): ... this. + * top.h (wait_sync_command_done): Declare. + * target-delegates.c: Regenerate. + 2015-09-09 Markus Metzger <markus.t.metzger@intel.com> * nat/linux-btrace.h (struct btrace_target_info) <ptr_bits>: Remove. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 5067222..4049d0a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -4662,7 +4662,7 @@ bpstat_do_actions_1 (bpstat *bsp) if (breakpoint_proceeded) { - if (interpreter_async && target_can_async_p ()) + if (interpreter_async) /* If we are in async mode, then the target might be still running, not stopped at any breakpoint, so nothing for us to do here -- just return to the event loop. */ @@ -11588,7 +11588,7 @@ until_break_command (char *arg, int from_tty, int anywhere) be deleted when the target stops. Otherwise, we're already stopped and delete breakpoints via cleanup chain. */ - if (target_can_async_p () && is_running (inferior_ptid)) + if (is_running (inferior_ptid)) { struct until_break_command_continuation_args *args = XNEW (struct until_break_command_continuation_args); diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c index eed881d..7b1f724 100644 --- a/gdb/inf-loop.c +++ b/gdb/inf-loop.c @@ -73,7 +73,7 @@ inferior_event_handler (enum inferior_event_type event_type, /* Unregister the inferior from the event loop. This is done so that when the inferior is not running we don't get distracted by spurious inferior output. */ - if (target_has_execution) + if (target_has_execution && target_can_async_p ()) target_async (0); } diff --git a/gdb/infcall.c b/gdb/infcall.c index ad5f004..734d6b5 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -36,6 +36,8 @@ #include "gdbthread.h" #include "event-top.h" #include "observer.h" +#include "top.h" +#include "interps.h" /* If we can't find a function's name from its address, we print this instead. */ @@ -388,10 +390,13 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) ptid_t call_thread_ptid = call_thread->ptid; int saved_sync_execution = sync_execution; int was_running = call_thread->state == THREAD_RUNNING; + int saved_interpreter_async = interpreter_async; /* Infcalls run synchronously, in the foreground. */ - if (target_can_async_p ()) - sync_execution = 1; + sync_execution = 1; + /* So that we don't print the prompt prematurely in + fetch_inferior_event. */ + interpreter_async = 0; call_thread->control.in_infcall = 1; @@ -404,25 +409,11 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) TRY { - int was_sync = sync_execution; - proceed (real_pc, GDB_SIGNAL_0); /* Inferior function calls are always synchronous, even if the - target supports asynchronous execution. Do here what - `proceed' itself does in sync mode. */ - if (target_can_async_p ()) - { - wait_for_inferior (); - normal_stop (); - /* 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 - inferior_event_handler, when an exception is thrown. */ - if (was_sync) - async_disable_stdin (); - } + target supports asynchronous execution. */ + wait_sync_command_done (); } CATCH (e, RETURN_MASK_ALL) { @@ -430,6 +421,13 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) } 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 + inferior_event_handler, when an exception is thrown. */ + sync_execution = saved_sync_execution; + interpreter_async = saved_interpreter_async; + /* At this point the current thread may have changed. Refresh CALL_THREAD as it could be invalid if its thread has exited. */ call_thread = find_thread_ptid (call_thread_ptid); @@ -470,8 +468,6 @@ run_inferior_call (struct thread_info *call_thread, CORE_ADDR real_pc) if (call_thread != NULL) call_thread->control.in_infcall = saved_in_infcall; - sync_execution = saved_sync_execution; - return caught_error; } diff --git a/gdb/infcmd.c b/gdb/infcmd.c index bdde49d..ce49777 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -504,13 +504,12 @@ prepare_execution_command (struct target_ops *target, int background) if (background && !target->to_can_async_p (target)) error (_("Asynchronous execution not supported on this target.")); - /* If we don't get a request of running in the bg, then we need - to simulate synchronous (fg) execution. */ - if (!background && target->to_can_async_p (target)) + if (!background) { - /* Simulate synchronous execution. Note no cleanup is necessary - for this. stdin is re-enabled whenever an error reaches the - top level. */ + /* If we get a request for running in the fg, then we need to + simulate synchronous (fg) execution. Note no cleanup is + necessary for this. stdin is re-enabled whenever an error + reaches the top level. */ async_disable_stdin (); } } @@ -937,44 +936,15 @@ step_1 (int skip_subroutines, int single_inst, char *count_string) make_cleanup (delete_longjmp_breakpoint_cleanup, &thread); } - /* In synchronous case, all is well; each step_once call will step once. */ - if (!target_can_async_p ()) - { - for (; count > 0; count--) - { - step_once (skip_subroutines, single_inst, count, thread); - - if (!target_has_execution) - break; - else - { - struct thread_info *tp = inferior_thread (); + /* Do only one step for now, before returning control to the event + loop. Let the continuation figure out how many other steps we + need to do, and handle them one at the time, through + step_once. */ + step_once (skip_subroutines, single_inst, count, thread); - if (!tp->control.stop_step || !tp->step_multi) - { - /* If we stopped for some reason that is not stepping - there are no further steps to make. */ - tp->step_multi = 0; - break; - } - } - } - - do_cleanups (cleanups); - } - else - { - /* In the case of an asynchronous target things get complicated; - do only one step for now, before returning control to the - event loop. Let the continuation figure out how many other - steps we need to do, and handle them one at the time, through - step_once. */ - step_once (skip_subroutines, single_inst, count, thread); - - /* We are running, and the continuation is installed. It will - disable the longjmp breakpoint as appropriate. */ - discard_cleanups (cleanups); - } + /* We are running, and the continuation is installed. It will + disable the longjmp breakpoint as appropriate. */ + discard_cleanups (cleanups); } struct step_1_continuation_args @@ -1033,6 +1003,7 @@ step_once (int skip_subroutines, int single_inst, int count, int thread) if (count > 0) { + struct step_1_continuation_args *args; /* Don't assume THREAD is a valid thread id. It is set to -1 if the longjmp breakpoint was not required. Use the INFERIOR_PTID thread instead, which is the same thread when @@ -1116,21 +1087,15 @@ step_once (int skip_subroutines, int single_inst, int count, int thread) tp->control.stepping_command = 1; proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); - /* For async targets, register a continuation to do any - additional steps. For sync targets, the caller will handle - further stepping. */ - if (target_can_async_p ()) - { - struct step_1_continuation_args *args = - XNEW (struct step_1_continuation_args); - - args->skip_subroutines = skip_subroutines; - args->single_inst = single_inst; - args->count = count; - args->thread = thread; + /* Register a continuation to do any additional steps. */ + args = XNEW (struct step_1_continuation_args); + args = xmalloc (sizeof (*args)); + args->skip_subroutines = skip_subroutines; + args->single_inst = single_inst; + args->count = count; + args->thread = thread; - add_intermediate_continuation (tp, step_1_continuation, args, xfree); - } + add_intermediate_continuation (tp, step_1_continuation, args, xfree); } } @@ -1442,7 +1407,7 @@ until_next_command (int from_tty) proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); - if (target_can_async_p () && is_running (inferior_ptid)) + if (is_running (inferior_ptid)) { struct until_next_continuation_args *cont_args; @@ -1801,8 +1766,6 @@ finish_forward (struct symbol *function, struct frame_info *frame) proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); discard_cleanups (old_chain); - if (!target_can_async_p ()) - do_all_continuations (0); } /* "finish": Set a temporary breakpoint at the place the selected @@ -2532,8 +2495,7 @@ attach_command_post_wait (char *args, int from_tty, int async_exec) /* The user requested a plain `attach', so be sure to leave the inferior stopped. */ - if (target_can_async_p ()) - async_enable_stdin (); + async_enable_stdin (); /* At least the current thread is already stopped. */ @@ -2663,6 +2625,7 @@ attach_command (char *args, int from_tty) E.g. Mach 3 or GNU hurd. */ if (!target_attach_no_wait) { + struct attach_command_continuation_args *a; struct inferior *inferior = current_inferior (); /* Careful here. See comments in inferior.h. Basically some @@ -2672,25 +2635,19 @@ attach_command (char *args, int from_tty) STOP_QUIETLY_NO_SIGSTOP is for. */ inferior->control.stop_soon = STOP_QUIETLY_NO_SIGSTOP; - if (target_can_async_p ()) - { - /* sync_execution mode. Wait for stop. */ - struct attach_command_continuation_args *a; - - a = XNEW (struct attach_command_continuation_args); - a->args = xstrdup (args); - a->from_tty = from_tty; - a->async_exec = async_exec; - add_inferior_continuation (attach_command_continuation, a, - attach_command_continuation_free_args); - - /* Done with ARGS. */ - do_cleanups (args_chain); - - return; - } - - wait_for_inferior (); + /* sync_execution mode. Wait for stop. */ + a = XNEW (struct attach_command_continuation_args); + a->args = xstrdup (args); + a->from_tty = from_tty; + a->async_exec = async_exec; + add_inferior_continuation (attach_command_continuation, a, + attach_command_continuation_free_args); + /* Done with ARGS. */ + do_cleanups (args_chain); + + if (!target_is_async_p ()) + mark_infrun_async_event_handler (); + return; } /* Done with ARGS. */ @@ -2731,6 +2688,7 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) if (is_executing (inferior_ptid)) { + struct attach_command_continuation_args *a; struct inferior *inferior = current_inferior (); /* We're going to install breakpoints, and poke at memory, @@ -2741,22 +2699,15 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) inferior->control.stop_soon = STOP_QUIETLY_REMOTE; /* Wait for stop before proceeding. */ - if (target_can_async_p ()) - { - struct attach_command_continuation_args *a; + a = XNEW (struct attach_command_continuation_args); + a->args = xstrdup (""); + a->from_tty = from_tty; + a->async_exec = async_exec; + add_inferior_continuation (attach_command_continuation, a, + attach_command_continuation_free_args); - a = XNEW (struct attach_command_continuation_args); - a->args = xstrdup (""); - a->from_tty = from_tty; - a->async_exec = async_exec; - add_inferior_continuation (attach_command_continuation, a, - attach_command_continuation_free_args); - - do_cleanups (old_chain); - return; - } - else - wait_for_inferior (); + do_cleanups (old_chain); + return; } async_exec = leave_running; diff --git a/gdb/infrun.c b/gdb/infrun.c index 70dffca..273c2bc 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -131,6 +131,14 @@ infrun_async (int enable) } } +/* See infrun.h. */ + +void +mark_infrun_async_event_handler (void) +{ + mark_async_event_handler (infrun_async_inferior_event_token); +} + /* When set, stop the 'step' command if we enter a function which has no line number information. The normal behavior is that we step over such function. */ @@ -3094,15 +3102,11 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal) discard_cleanups (old_chain); - /* Wait for it to stop (if not standalone) - and in any case decode why it stopped, and act accordingly. */ - /* Do this only if we are not using the event loop, or if the target - does not support asynchronous execution. */ + /* Tell the event loop to wait for it to stop. If the target + supports asynchronous execution, it'll do this from within + target_resume. */ if (!target_can_async_p ()) - { - wait_for_inferior (); - normal_stop (); - } + mark_async_event_handler (infrun_async_inferior_event_token); } @@ -3766,7 +3770,8 @@ fetch_inferior_event (void *client_data) make_cleanup_restore_integer (&execution_direction); execution_direction = target_execution_direction (); - ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, TARGET_WNOHANG); + ecs->ptid = do_target_wait (waiton_ptid, &ecs->ws, + target_can_async_p () ? TARGET_WNOHANG : 0); if (debug_infrun) print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws); @@ -7520,10 +7525,10 @@ prepare_to_wait (struct execution_control_state *ecs) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n"); - /* This is the old end of the while loop. Let everybody know we - want to wait for the inferior some more and get called again - soon. */ ecs->wait_some_more = 1; + + if (!target_is_async_p ()) + mark_infrun_async_event_handler (); } /* We are done with the step range of a step/next/si/ni command. @@ -8816,14 +8821,6 @@ static const struct internalvar_funcs siginfo_funcs = static void infrun_async_inferior_event_handler (gdb_client_data data) { - /* If the target is closed while this event source is marked, we - will reach here without execution, or a target to call - target_wait on, which is an error. Instead of tracking whether - the target has been popped already, or whether we do have threads - with pending statutes, simply ignore the event. */ - if (!target_is_async_p ()) - return; - inferior_event_handler (INF_REG_EVENT, NULL); } diff --git a/gdb/infrun.h b/gdb/infrun.h index 7978d2c..c5b201f 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -197,6 +197,10 @@ enum gdb_signal gdb_signal_from_command (int num); /* Enables/disables infrun's async event source in the event loop. */ extern void infrun_async (int enable); +/* Call infrun's event handler the next time through the event + loop. */ +extern void mark_infrun_async_event_handler (void); + /* The global queue of threads that need to do a step-over operation to get past e.g., a breakpoint. */ extern struct thread_info *step_over_queue_head; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 51541d5..6b01a51 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -3442,12 +3442,6 @@ linux_nat_wait_1 (struct target_ops *ops, target_pid_to_str (lp->ptid)); } - if (!target_is_async_p ()) - { - /* Causes SIGINT to be passed on to the attached process. */ - set_sigint_trap (); - } - /* But if we don't find a pending event, we'll have to wait. Always pull all events out of the kernel. We'll randomly select an event LWP out of all that have events, to prevent starvation. */ @@ -3518,9 +3512,6 @@ linux_nat_wait_1 (struct target_ops *ops, ourstatus->kind = TARGET_WAITKIND_NO_RESUMED; - if (!target_is_async_p ()) - clear_sigint_trap (); - restore_child_signals_mask (&prev_mask); return minus_one_ptid; } @@ -3546,9 +3537,6 @@ linux_nat_wait_1 (struct target_ops *ops, sigsuspend (&suspend_mask); } - if (!target_is_async_p ()) - clear_sigint_trap (); - gdb_assert (lp); status = lp->status; @@ -4629,17 +4617,6 @@ static int async_terminal_is_ours = 1; static void linux_nat_terminal_inferior (struct target_ops *self) { - /* Like target_terminal_inferior, use target_can_async_p, not - target_is_async_p, since at this point the target is not async - yet. If it can async, then we know it will become async prior to - resume. */ - if (!target_can_async_p ()) - { - /* Async mode is disabled. */ - child_terminal_inferior (self); - return; - } - child_terminal_inferior (self); /* Calls to target_terminal_*() are meant to be idempotent. */ diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 99ce385..0935c8f 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -309,16 +309,8 @@ mi_execute_command_wrapper (const char *cmd) static void mi_on_sync_execution_done (void) { - /* MI generally prints a prompt after a command, indicating it's - ready for further input. However, due to an historical wart, if - MI async, and a (CLI) synchronous command was issued, then we - will print the prompt right after printing "^running", even if we - cannot actually accept any input until the target stops. See - mi_on_resume. However, if the target is async but MI is sync, - then we need to output the MI prompt now, to replicate gdb's - behavior when neither the target nor MI are async. (Note this - observer is only called by the asynchronous target event handling - code.) */ + /* If MI is sync, then output the MI prompt now, indicating we're + ready for further input. */ if (!mi_async_p ()) { fputs_unfiltered ("(gdb) \n", raw_stdout); @@ -333,20 +325,12 @@ mi_execute_command_input_handler (char *cmd) { mi_execute_command_wrapper (cmd); - /* MI generally prints a prompt after a command, indicating it's - ready for further input. However, due to an historical wart, if - MI is async, and a synchronous command was issued, then we will - print the prompt right after printing "^running", even if we - cannot actually accept any input until the target stops. See - mi_on_resume. - - If MI is not async, then we print the prompt when the command - finishes. If the target is sync, that means output the prompt - now, as in that case executing a command doesn't return until the - command is done. However, if the target is async, we go back to - the event loop and output the prompt in the - 'synchronous_command_done' observer. */ - if (!target_is_async_p () || !sync_execution) + /* Print a prompt, indicating we're ready for further input, unless + we just started a synchronous command. In that case, we're about + 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) { fputs_unfiltered ("(gdb) \n", raw_stdout); gdb_flush (raw_stdout); diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c index ddcad94..8d51b6c 100644 --- a/gdb/target-delegates.c +++ b/gdb/target-delegates.c @@ -117,12 +117,6 @@ delegate_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *a } static ptid_t -tdefault_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) -{ - noprocess (); -} - -static ptid_t debug_wait (struct target_ops *self, ptid_t arg1, struct target_waitstatus *arg2, int arg3) { ptid_t result; @@ -4251,7 +4245,7 @@ install_dummy_methods (struct target_ops *ops) ops->to_detach = tdefault_detach; ops->to_disconnect = tdefault_disconnect; ops->to_resume = tdefault_resume; - ops->to_wait = tdefault_wait; + ops->to_wait = default_target_wait; ops->to_fetch_registers = tdefault_fetch_registers; ops->to_store_registers = tdefault_store_registers; ops->to_prepare_to_store = tdefault_prepare_to_store; diff --git a/gdb/target.c b/gdb/target.c index ea541aa..3da984e 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -2233,6 +2233,17 @@ target_wait (ptid_t ptid, struct target_waitstatus *status, int options) return (current_target.to_wait) (¤t_target, ptid, status, options); } +/* See target.h. */ + +ptid_t +default_target_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, + int options) +{ + status->kind = TARGET_WAITKIND_IGNORE; + return minus_one_ptid; +} + char * target_pid_to_str (ptid_t ptid) { diff --git a/gdb/target.h b/gdb/target.h index 37e4edb..0b85adf 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -471,7 +471,7 @@ struct target_ops ptid_t (*to_wait) (struct target_ops *, ptid_t, struct target_waitstatus *, int TARGET_DEBUG_PRINTER (target_debug_print_options)) - TARGET_DEFAULT_NORETURN (noprocess ()); + TARGET_DEFAULT_FUNC (default_target_wait); void (*to_fetch_registers) (struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE (); void (*to_store_registers) (struct target_ops *, struct regcache *, int) @@ -1327,6 +1327,13 @@ extern void target_resume (ptid_t ptid, int step, enum gdb_signal signal); extern ptid_t target_wait (ptid_t ptid, struct target_waitstatus *status, int options); +/* The default target_ops::to_wait implementation. */ + +extern ptid_t default_target_wait (struct target_ops *ops, + ptid_t ptid, + struct target_waitstatus *status, + int options); + /* Fetch at least register REGNO, or all regs if regno == -1. No result. */ extern void target_fetch_registers (struct regcache *regcache, int regno); @@ -368,6 +368,16 @@ check_frame_language_change (void) /* See top.h. */ void +wait_sync_command_done (void) +{ + while (gdb_do_one_event () >= 0) + if (!sync_execution) + break; +} + +/* See top.h. */ + +void maybe_wait_sync_command_done (int was_sync) { /* If the interpreter is in sync mode (we're running a user @@ -375,11 +385,7 @@ maybe_wait_sync_command_done (int was_sync) just ran a synchronous command that started the target, wait for that command to end. */ if (!interpreter_async && !was_sync && sync_execution) - { - while (gdb_do_one_event () >= 0) - if (!sync_execution) - break; - } + wait_sync_command_done (); } /* Execute the line P as a command, in the current user context. @@ -50,6 +50,9 @@ extern void execute_command (char *, int); extern void maybe_wait_sync_command_done (int was_sync); +/* Wait for a synchronous execution command to end. */ +extern void wait_sync_command_done (void); + extern void check_frame_language_change (void); /* Prepare for execution of a command. |