Async mode fixes.
* Makefile.in (infcmd.o, inf-loop.o): Update dependencies. * breakpoint.c (bpstat_do_actions): In async mode, don't jump to top expecting stop_bpstat to be already updated. * event-loop.c (start_event_loop): Call async_enable_stdin on exception. * event-top.c (async_enable_stdin): Do nothing if sync_execution is not set. (command_handler): Do not setup continuation here. (command_line_handler_continuation): Move to... * top.c (command_line_handler_continuation): ... here. (execute_command): In async mode, register continuation. Don't check frame's language in running in async mode. * exceptions.c (throw_exception): Don't do exec_error_cleanups. * inf-loop.c (complete_execution): Inline into... (inferior_event_handler): ... here. Clear target_executing before doing any cleanups. Don't try to show prompt if the target was resumed. * infcmd.c (signal_command): Add support for async mode. (finish_command): Only add continuation if the target was successfully resumed. * remote.c (init_async_opts): Register to_get_thread_local_address handler. * mi/mi-interp.c (mi_cmd_interpreter_exec): Don't mess with sync_execution. * tui/tui-interp.c (tui_command_loop): Call async_enable_stdin on exception.
This commit is contained in:
parent
c04ea773f9
commit
32c1e744c1
12 changed files with 237 additions and 127 deletions
|
@ -1,3 +1,34 @@
|
|||
2008-03-14 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
Async mode fixes.
|
||||
* Makefile.in (infcmd.o, inf-loop.o): Update dependencies.
|
||||
* breakpoint.c (bpstat_do_actions): In async mode,
|
||||
don't jump to top expecting stop_bpstat to be already
|
||||
updated.
|
||||
* event-loop.c (start_event_loop): Call async_enable_stdin
|
||||
on exception.
|
||||
* event-top.c (async_enable_stdin): Do nothing if sync_execution
|
||||
is not set.
|
||||
(command_handler): Do not setup continuation here.
|
||||
(command_line_handler_continuation): Move to...
|
||||
* top.c (command_line_handler_continuation): ... here.
|
||||
(execute_command): In async mode, register continuation.
|
||||
Don't check frame's language in running in async mode.
|
||||
* exceptions.c (throw_exception): Don't do exec_error_cleanups.
|
||||
* inf-loop.c (complete_execution): Inline into...
|
||||
(inferior_event_handler): ... here. Clear target_executing before
|
||||
doing any cleanups. Don't try to show prompt if the target was
|
||||
resumed.
|
||||
* infcmd.c (signal_command): Add support for async mode.
|
||||
(finish_command): Only add continuation if the target was
|
||||
successfully resumed.
|
||||
* remote.c (init_async_opts): Register to_get_thread_local_address
|
||||
handler.
|
||||
* mi/mi-interp.c (mi_cmd_interpreter_exec): Don't mess
|
||||
with sync_execution.
|
||||
* tui/tui-interp.c (tui_command_loop): Call async_enable_stdin
|
||||
on exception.
|
||||
|
||||
2008-03-14 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* corefile.c (reopen_exec_file): Use exec_bfd_mtime.
|
||||
|
|
|
@ -2291,9 +2291,10 @@ infcmd.o: infcmd.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
|||
$(objfiles_h) $(completer_h) $(ui_out_h) $(event_top_h) \
|
||||
$(parser_defs_h) $(regcache_h) $(reggroups_h) $(block_h) \
|
||||
$(solib_h) $(gdb_assert_h) $(observer_h) $(target_descriptions_h) \
|
||||
$(user_regs_h)
|
||||
$(user_regs_h) $(exceptions_h)
|
||||
inf-loop.o: inf-loop.c $(defs_h) $(inferior_h) $(target_h) $(event_loop_h) \
|
||||
$(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h)
|
||||
$(event_top_h) $(inf_loop_h) $(remote_h) $(exceptions_h) \
|
||||
$(language_h)
|
||||
inflow.o: inflow.c $(defs_h) $(frame_h) $(inferior_h) $(command_h) \
|
||||
$(serial_h) $(terminal_h) $(target_h) $(gdbthread_h) $(gdb_string_h) \
|
||||
$(inflow_h) $(gdb_select_h)
|
||||
|
|
|
@ -2114,11 +2114,30 @@ top:
|
|||
do_cleanups (this_cmd_tree_chain);
|
||||
|
||||
if (breakpoint_proceeded)
|
||||
/* The inferior is proceeded by the command; bomb out now.
|
||||
The bpstat chain has been blown away by wait_for_inferior.
|
||||
But since execution has stopped again, there is a new bpstat
|
||||
to look at, so start over. */
|
||||
goto top;
|
||||
{
|
||||
if (target_can_async_p ())
|
||||
/* 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. */
|
||||
break;
|
||||
else
|
||||
/* In sync mode, when execute_control_command returns
|
||||
we're already standing on the next breakpoint.
|
||||
Breakpoint commands for that stop were not run,
|
||||
since execute_command does not run breakpoint
|
||||
commands -- only command_line_handler does, but
|
||||
that one is not involved in execution of breakpoint
|
||||
commands. So, we can now execute breakpoint commands.
|
||||
There's an implicit assumption that we're called with
|
||||
stop_bpstat, so our parameter is the new bpstat to
|
||||
handle.
|
||||
It should be noted that making execute_command do
|
||||
bpstat actions is not an option -- in this case we'll
|
||||
have recursive invocation of bpstat for each breakpoint
|
||||
with a command, and can easily blow up GDB stack. */
|
||||
goto top;
|
||||
}
|
||||
}
|
||||
do_cleanups (old_chain);
|
||||
}
|
||||
|
|
|
@ -411,6 +411,10 @@ start_event_loop (void)
|
|||
|
||||
if (gdb_result == 0)
|
||||
{
|
||||
/* If any exception escaped to here, we better enable
|
||||
stdin. Otherwise, any command that calls async_disable_stdin,
|
||||
and then throws, will leave stdin inoperable. */
|
||||
async_enable_stdin ((void *) 0);
|
||||
/* FIXME: this should really be a call to a hook that is
|
||||
interface specific, because interfaces can display the
|
||||
prompt in their own way. */
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
static void rl_callback_read_char_wrapper (gdb_client_data client_data);
|
||||
static void command_line_handler (char *rl);
|
||||
static void command_line_handler_continuation (struct continuation_arg *arg);
|
||||
static void change_line_handler (void);
|
||||
static void change_annotation_level (void);
|
||||
static void command_handler (char *command);
|
||||
|
@ -438,13 +437,16 @@ stdin_event_handler (int error, gdb_client_data client_data)
|
|||
void
|
||||
async_enable_stdin (void *dummy)
|
||||
{
|
||||
/* 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 ();
|
||||
pop_prompt ();
|
||||
sync_execution = 0;
|
||||
if (sync_execution)
|
||||
{
|
||||
/* 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 ();
|
||||
pop_prompt ();
|
||||
sync_execution = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable reads from stdin (the console) marking the command as
|
||||
|
@ -480,8 +482,6 @@ command_handler (char *command)
|
|||
{
|
||||
struct cleanup *old_chain;
|
||||
int stdin_is_tty = ISATTY (stdin);
|
||||
struct continuation_arg *arg1;
|
||||
struct continuation_arg *arg2;
|
||||
long time_at_cmd_start;
|
||||
#ifdef HAVE_SBRK
|
||||
long space_at_cmd_start = 0;
|
||||
|
@ -517,24 +517,6 @@ command_handler (char *command)
|
|||
|
||||
execute_command (command, instream == stdin);
|
||||
|
||||
/* Set things up for this function to be compete later, once the
|
||||
execution has completed, if we are doing an execution command,
|
||||
otherwise, just go ahead and finish. */
|
||||
if (target_can_async_p () && target_executing)
|
||||
{
|
||||
arg1 =
|
||||
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
|
||||
arg2 =
|
||||
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
|
||||
arg1->next = arg2;
|
||||
arg2->next = NULL;
|
||||
arg1->data.longint = time_at_cmd_start;
|
||||
#ifdef HAVE_SBRK
|
||||
arg2->data.longint = space_at_cmd_start;
|
||||
#endif
|
||||
add_continuation (command_line_handler_continuation, arg1);
|
||||
}
|
||||
|
||||
/* Do any commands attached to breakpoint we stopped at. Only if we
|
||||
are always running synchronously. Or if we have just executed a
|
||||
command that doesn't start the target. */
|
||||
|
@ -567,43 +549,6 @@ command_handler (char *command)
|
|||
}
|
||||
}
|
||||
|
||||
/* Do any commands attached to breakpoint we stopped at. Only if we
|
||||
are always running synchronously. Or if we have just executed a
|
||||
command that doesn't start the target. */
|
||||
void
|
||||
command_line_handler_continuation (struct continuation_arg *arg)
|
||||
{
|
||||
extern int display_time;
|
||||
extern int display_space;
|
||||
|
||||
long time_at_cmd_start = arg->data.longint;
|
||||
long space_at_cmd_start = arg->next->data.longint;
|
||||
|
||||
bpstat_do_actions (&stop_bpstat);
|
||||
/*do_cleanups (old_chain); *//*?????FIXME????? */
|
||||
|
||||
if (display_time)
|
||||
{
|
||||
long cmd_time = get_run_time () - time_at_cmd_start;
|
||||
|
||||
printf_unfiltered (_("Command execution time: %ld.%06ld\n"),
|
||||
cmd_time / 1000000, cmd_time % 1000000);
|
||||
}
|
||||
if (display_space)
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
char *lim = (char *) sbrk (0);
|
||||
long space_now = lim - lim_at_start;
|
||||
long space_diff = space_now - space_at_cmd_start;
|
||||
|
||||
printf_unfiltered (_("Space used: %ld (%c%ld for this command)\n"),
|
||||
space_now,
|
||||
(space_diff >= 0 ? '+' : '-'),
|
||||
space_diff);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle a complete line of input. This is called by the callback
|
||||
mechanism within the readline library. Deal with incomplete commands
|
||||
as well, by saving the partial input in a global buffer. */
|
||||
|
|
|
@ -221,10 +221,12 @@ throw_exception (struct gdb_exception exception)
|
|||
|
||||
disable_current_display ();
|
||||
do_cleanups (ALL_CLEANUPS);
|
||||
/* When we implement non-stop mode, this should be redone. If we get
|
||||
exception in a command pertaining to one thread, or maybe even not
|
||||
involving inferior at all, we should not do exec cleanups for all
|
||||
threads. */
|
||||
if (target_can_async_p () && !target_executing)
|
||||
do_exec_cleanups (ALL_CLEANUPS);
|
||||
if (sync_execution)
|
||||
do_exec_error_cleanups (ALL_CLEANUPS);
|
||||
|
||||
/* Jump to the containing catch_errors() call, communicating REASON
|
||||
to that call via setjmp's return value. Note that REASON can't
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "inf-loop.h"
|
||||
#include "remote.h"
|
||||
#include "exceptions.h"
|
||||
#include "language.h"
|
||||
|
||||
static int fetch_inferior_event_wrapper (gdb_client_data client_data);
|
||||
static void complete_execution (void);
|
||||
|
||||
void
|
||||
inferior_event_handler_wrapper (gdb_client_data client_data)
|
||||
|
@ -43,6 +43,7 @@ void
|
|||
inferior_event_handler (enum inferior_event_type event_type,
|
||||
gdb_client_data client_data)
|
||||
{
|
||||
int was_sync = 0;
|
||||
switch (event_type)
|
||||
{
|
||||
case INF_ERROR:
|
||||
|
@ -70,11 +71,52 @@ inferior_event_handler (enum inferior_event_type event_type,
|
|||
break;
|
||||
|
||||
case INF_EXEC_COMPLETE:
|
||||
/* Is there anything left to do for the command issued to
|
||||
complete? */
|
||||
|
||||
/* This is the first thing to do -- so that continuations know that
|
||||
the target is stopped. For example, command_line_handler_continuation
|
||||
will run breakpoint commands, and if we think that the target is
|
||||
running, we'll refuse to execute most commands. MI continuation
|
||||
presently uses target_executing to either print or not print *stopped. */
|
||||
target_executing = 0;
|
||||
|
||||
/* 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)
|
||||
target_async (NULL, 0);
|
||||
|
||||
/* Calls to do_exec_error_cleanup below will call async_enable_stdin,
|
||||
and that resets 'sync_execution'. However, if we were running
|
||||
in sync execution mode, we also need to display the prompt. */
|
||||
was_sync = sync_execution;
|
||||
|
||||
if (was_sync)
|
||||
do_exec_error_cleanups (ALL_CLEANUPS);
|
||||
|
||||
do_all_continuations ();
|
||||
/* Reset things after target has stopped for the async commands. */
|
||||
complete_execution ();
|
||||
|
||||
if (current_language != expected_language)
|
||||
{
|
||||
if (language_mode == language_mode_auto)
|
||||
{
|
||||
language_info (1); /* Print what changed. */
|
||||
}
|
||||
}
|
||||
|
||||
/* If the continuation did not start the target again,
|
||||
prepare for interation with the user. */
|
||||
if (!target_executing)
|
||||
{
|
||||
if (was_sync)
|
||||
{
|
||||
display_gdb_prompt (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exec_done_display_p)
|
||||
printf_unfiltered (_("completed.\n"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case INF_EXEC_CONTINUE:
|
||||
|
@ -103,29 +145,3 @@ fetch_inferior_event_wrapper (gdb_client_data client_data)
|
|||
fetch_inferior_event (client_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Reset proper settings after an asynchronous command has finished.
|
||||
If the execution command was in synchronous mode, register stdin
|
||||
with the event loop, and reset the prompt. */
|
||||
|
||||
static void
|
||||
complete_execution (void)
|
||||
{
|
||||
target_executing = 0;
|
||||
|
||||
/* 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. */
|
||||
target_async (NULL, 0);
|
||||
|
||||
if (sync_execution)
|
||||
{
|
||||
do_exec_error_cleanups (ALL_CLEANUPS);
|
||||
display_gdb_prompt (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exec_done_display_p)
|
||||
printf_unfiltered (_("completed.\n"));
|
||||
}
|
||||
}
|
||||
|
|
29
gdb/infcmd.c
29
gdb/infcmd.c
|
@ -48,6 +48,7 @@
|
|||
#include "observer.h"
|
||||
#include "target-descriptions.h"
|
||||
#include "user-regs.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
/* Functions exported for general use, in inferior.h: */
|
||||
|
||||
|
@ -1005,10 +1006,28 @@ static void
|
|||
signal_command (char *signum_exp, int from_tty)
|
||||
{
|
||||
enum target_signal oursig;
|
||||
int async_exec = 0;
|
||||
|
||||
dont_repeat (); /* Too dangerous. */
|
||||
ERROR_NO_INFERIOR;
|
||||
|
||||
/* Find out whether we must run in the background. */
|
||||
if (signum_exp != NULL)
|
||||
async_exec = strip_bg_char (&signum_exp);
|
||||
|
||||
/* If we must run in the background, but the target can't do it,
|
||||
error out. */
|
||||
if (async_exec && !target_can_async_p ())
|
||||
error (_("Asynchronous execution not supported on this target."));
|
||||
|
||||
/* If we are not asked to run in the bg, then prepare to run in the
|
||||
foreground, synchronously. */
|
||||
if (!async_exec && target_can_async_p ())
|
||||
{
|
||||
/* Simulate synchronous execution. */
|
||||
async_disable_stdin ();
|
||||
}
|
||||
|
||||
if (!signum_exp)
|
||||
error_no_arg (_("signal number"));
|
||||
|
||||
|
@ -1321,10 +1340,15 @@ finish_command (char *arg, int from_tty)
|
|||
print_stack_frame (get_selected_frame (NULL), 1, LOCATION);
|
||||
}
|
||||
|
||||
proceed_to_finish = 1; /* We want stop_registers, please... */
|
||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
||||
|
||||
/* If running asynchronously and the target support asynchronous
|
||||
execution, set things up for the rest of the finish command to be
|
||||
completed later on, when gdb has detected that the target has
|
||||
stopped, in fetch_inferior_event. */
|
||||
stopped, in fetch_inferior_event.
|
||||
Setup it only after proceed, so that if proceed throws, we don't
|
||||
set continuation. */
|
||||
if (target_can_async_p ())
|
||||
{
|
||||
arg1 =
|
||||
|
@ -1342,9 +1366,6 @@ finish_command (char *arg, int from_tty)
|
|||
add_continuation (finish_command_continuation, arg1);
|
||||
}
|
||||
|
||||
proceed_to_finish = 1; /* We want stop_registers, please... */
|
||||
proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
|
||||
|
||||
/* Do this only if not running asynchronously or if the target
|
||||
cannot do async execution. Otherwise, complete this command when
|
||||
the target actually stops, in fetch_inferior_event. */
|
||||
|
|
|
@ -224,23 +224,13 @@ mi_cmd_interpreter_exec (char *command, char **argv, int argc)
|
|||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
/* We had to set sync_execution = 0 for the mi (well really for Project
|
||||
Builder's use of the mi - particularly so interrupting would work.
|
||||
But for console commands to work, we need to initialize it to 1 -
|
||||
since that is what the cli expects - before running the command,
|
||||
and then set it back to 0 when we are done. */
|
||||
sync_execution = 1;
|
||||
{
|
||||
struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
|
||||
if (e.reason < 0)
|
||||
{
|
||||
mi_error_message = xstrdup (e.message);
|
||||
result = MI_CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
do_exec_error_cleanups (ALL_CLEANUPS);
|
||||
sync_execution = 0;
|
||||
struct gdb_exception e = interp_exec (interp_to_use, argv[i]);
|
||||
if (e.reason < 0)
|
||||
{
|
||||
mi_error_message = xstrdup (e.message);
|
||||
result = MI_CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mi_remove_notify_hooks ();
|
||||
|
|
|
@ -7348,6 +7348,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
|
|||
remote_async_ops.to_stop = remote_stop;
|
||||
remote_async_ops.to_xfer_partial = remote_xfer_partial;
|
||||
remote_async_ops.to_rcmd = remote_rcmd;
|
||||
remote_async_ops.to_get_thread_local_address
|
||||
= remote_get_thread_local_address;
|
||||
remote_async_ops.to_stratum = process_stratum;
|
||||
remote_async_ops.to_has_all_memory = 1;
|
||||
remote_async_ops.to_has_memory = 1;
|
||||
|
|
77
gdb/top.c
77
gdb/top.c
|
@ -364,6 +364,42 @@ do_chdir_cleanup (void *old_dir)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Do any commands attached to breakpoint we stopped at. Only if we
|
||||
are always running synchronously. Or if we have just executed a
|
||||
command that doesn't start the target. */
|
||||
static void
|
||||
command_line_handler_continuation (struct continuation_arg *arg)
|
||||
{
|
||||
extern int display_time;
|
||||
extern int display_space;
|
||||
|
||||
long time_at_cmd_start = arg->data.longint;
|
||||
long space_at_cmd_start = arg->next->data.longint;
|
||||
|
||||
bpstat_do_actions (&stop_bpstat);
|
||||
|
||||
if (display_time)
|
||||
{
|
||||
long cmd_time = get_run_time () - time_at_cmd_start;
|
||||
|
||||
printf_unfiltered (_("Command execution time: %ld.%06ld\n"),
|
||||
cmd_time / 1000000, cmd_time % 1000000);
|
||||
}
|
||||
if (display_space)
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
char *lim = (char *) sbrk (0);
|
||||
long space_now = lim - lim_at_start;
|
||||
long space_diff = space_now - space_at_cmd_start;
|
||||
|
||||
printf_unfiltered (_("Space used: %ld (%c%ld for this command)\n"),
|
||||
space_now,
|
||||
(space_diff >= 0 ? '+' : '-'),
|
||||
space_diff);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute the line P as a command.
|
||||
Pass FROM_TTY as second argument to the defining function. */
|
||||
|
||||
|
@ -374,6 +410,27 @@ execute_command (char *p, int from_tty)
|
|||
enum language flang;
|
||||
static int warned = 0;
|
||||
char *line;
|
||||
struct continuation_arg *arg1;
|
||||
struct continuation_arg *arg2;
|
||||
long time_at_cmd_start;
|
||||
#ifdef HAVE_SBRK
|
||||
long space_at_cmd_start = 0;
|
||||
#endif
|
||||
extern int display_time;
|
||||
extern int display_space;
|
||||
|
||||
if (target_can_async_p ())
|
||||
{
|
||||
time_at_cmd_start = get_run_time ();
|
||||
|
||||
if (display_space)
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
char *lim = (char *) sbrk (0);
|
||||
space_at_cmd_start = lim - lim_at_start;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
free_all_values ();
|
||||
|
||||
|
@ -470,7 +527,7 @@ execute_command (char *p, int from_tty)
|
|||
/* FIXME: This should be cacheing the frame and only running when
|
||||
the frame changes. */
|
||||
|
||||
if (target_has_stack)
|
||||
if (!target_executing && target_has_stack)
|
||||
{
|
||||
flang = get_frame_language ();
|
||||
if (!warned
|
||||
|
@ -481,6 +538,24 @@ execute_command (char *p, int from_tty)
|
|||
warned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set things up for this function to be compete later, once the
|
||||
execution has completed, if we are doing an execution command,
|
||||
otherwise, just go ahead and finish. */
|
||||
if (target_can_async_p () && target_executing)
|
||||
{
|
||||
arg1 =
|
||||
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
|
||||
arg2 =
|
||||
(struct continuation_arg *) xmalloc (sizeof (struct continuation_arg));
|
||||
arg1->next = arg2;
|
||||
arg2->next = NULL;
|
||||
arg1->data.longint = time_at_cmd_start;
|
||||
#ifdef HAVE_SBRK
|
||||
arg2->data.longint = space_at_cmd_start;
|
||||
#endif
|
||||
add_continuation (command_line_handler_continuation, arg1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read commands from `instream' and execute them
|
||||
|
|
|
@ -164,6 +164,10 @@ tui_command_loop (void *data)
|
|||
|
||||
if (result == 0)
|
||||
{
|
||||
/* If any exception escaped to here, we better enable
|
||||
stdin. Otherwise, any command that calls async_disable_stdin,
|
||||
and then throws, will leave stdin inoperable. */
|
||||
async_enable_stdin ((void *) 0);
|
||||
/* FIXME: this should really be a call to a hook that is
|
||||
interface specific, because interfaces can display the
|
||||
prompt in their own way. */
|
||||
|
|
Loading…
Reference in a new issue