aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog31
-rw-r--r--gdb/Makefile.in5
-rw-r--r--gdb/breakpoint.c29
-rw-r--r--gdb/event-loop.c4
-rw-r--r--gdb/event-top.c75
-rw-r--r--gdb/exceptions.c6
-rw-r--r--gdb/inf-loop.c78
-rw-r--r--gdb/infcmd.c29
-rw-r--r--gdb/mi/mi-interp.c24
-rw-r--r--gdb/remote.c2
-rw-r--r--gdb/top.c77
-rw-r--r--gdb/tui/tui-interp.c4
12 files changed, 237 insertions, 127 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 082c44c..9526ba3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 04db233..a3e73b9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 4fbda0b..6830efe 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -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);
}
diff --git a/gdb/event-loop.c b/gdb/event-loop.c
index 9a04e32..ceff699 100644
--- a/gdb/event-loop.c
+++ b/gdb/event-loop.c
@@ -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. */
diff --git a/gdb/event-top.c b/gdb/event-top.c
index f798eee..79dd4c3 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -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. */
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index ae30367..89d1455 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -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
diff --git a/gdb/inf-loop.c b/gdb/inf-loop.c
index b6f8bb8..c4fb111 100644
--- a/gdb/inf-loop.c
+++ b/gdb/inf-loop.c
@@ -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"));
- }
-}
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 70bf695..3a22c1c 100644
--- a/gdb/infcmd.c
+++ b/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. */
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 96229a0..05a64d8 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -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 ();
diff --git a/gdb/remote.c b/gdb/remote.c
index 88cde58..73fcc2a 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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;
diff --git a/gdb/top.c b/gdb/top.c
index c205ec3..3b9aaab 100644
--- a/gdb/top.c
+++ b/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
diff --git a/gdb/tui/tui-interp.c b/gdb/tui/tui-interp.c
index ca2e743..8a16678 100644
--- a/gdb/tui/tui-interp.c
+++ b/gdb/tui/tui-interp.c
@@ -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. */