/* Top level stuff for GDB, the GNU debugger.
- Copyright (C) 1999-2013 Free Software Foundation, Inc.
+ Copyright (C) 1999-2015 Free Software Foundation, Inc.
Written by Elena Zannoni <ezannoni@cygnus.com> of Cygnus Solutions.
#include "defs.h"
#include "top.h"
#include "inferior.h"
+#include "infrun.h"
#include "target.h"
#include "terminal.h" /* for job_control */
#include "event-loop.h"
#include "event-top.h"
#include "interps.h"
#include <signal.h>
-#include "exceptions.h"
#include "cli/cli-script.h" /* for reset_command_nest_depth */
#include "main.h"
#include "gdbthread.h"
#ifdef STOP_SIGNAL
static void async_stop_sig (gdb_client_data);
#endif
+static void async_sigterm_handler (gdb_client_data arg);
/* Readline offers an alternate interface, via callback
functions. These are all included in the file callback.c in the
read commands from. */
int input_fd;
+/* Used by the stdin event handler to compensate for missed stdin events.
+ Setting this to a non-zero value inside an stdin callback makes the callback
+ run again. */
+int call_stdin_event_handler_again_p;
+
/* Signal handling variables. */
/* Each of these is a pointer to a function that the event loop will
invoke if the corresponding signal has received. The real signal
#ifdef STOP_SIGNAL
static struct async_signal_handler *sigtstp_token;
#endif
+static struct async_signal_handler *async_sigterm_token;
/* Structure to save a partially entered command. This is used when
the user types '\' at the end of a command line. This is necessary
}
/* Initialize all the necessary variables, start the event loop,
- register readline, and stdin, start the loop. */
+ register readline, and stdin, start the loop. The DATA is the
+ interpreter data cookie, ignored for now. */
+
void
-cli_command_loop (void)
+cli_command_loop (void *data)
{
display_gdb_prompt (0);
else
{
/* Turn off editing by using gdb_readline2. */
- rl_callback_handler_remove ();
+ gdb_rl_callback_handler_remove ();
call_readline = gdb_readline2;
/* Set up the command handler as well, in case we are called as
}
}
+/* The functions below are wrappers for rl_callback_handler_remove and
+ rl_callback_handler_install that keep track of whether the callback
+ handler is installed in readline. This is necessary because after
+ handling a target event of a background execution command, we may
+ need to reinstall the callback handler if it was removed due to a
+ secondary prompt. See gdb_readline_wrapper_line. We don't
+ unconditionally install the handler for every target event because
+ that also clears the line buffer, thus installing it while the user
+ is typing would lose input. */
+
+/* Whether we've registered a callback handler with readline. */
+static int callback_handler_installed;
+
+/* See event-top.h, and above. */
+
+void
+gdb_rl_callback_handler_remove (void)
+{
+ rl_callback_handler_remove ();
+ callback_handler_installed = 0;
+}
+
+/* See event-top.h, and above. Note this wrapper doesn't have an
+ actual callback parameter because we always install
+ INPUT_HANDLER. */
+
+void
+gdb_rl_callback_handler_install (const char *prompt)
+{
+ /* Calling rl_callback_handler_install resets readline's input
+ buffer. Calling this when we were already processing input
+ therefore loses input. */
+ gdb_assert (!callback_handler_installed);
+
+ rl_callback_handler_install (prompt, input_handler);
+ callback_handler_installed = 1;
+}
+
+/* See event-top.h, and above. */
+
+void
+gdb_rl_callback_handler_reinstall (void)
+{
+ if (!callback_handler_installed)
+ {
+ /* Passing NULL as prompt argument tells readline to not display
+ a prompt. */
+ gdb_rl_callback_handler_install (NULL);
+ }
+}
+
/* Displays the prompt. If the argument NEW_PROMPT is NULL, the
prompt that is displayed is the current top level prompt.
Otherwise, it displays whatever NEW_PROMPT is as a local/secondary
3. On prompting for pagination. */
void
-display_gdb_prompt (char *new_prompt)
+display_gdb_prompt (const char *new_prompt)
{
char *actual_gdb_prompt = NULL;
struct cleanup *old_chain;
/* Reset the nesting depth used when trace-commands is set. */
reset_command_nest_depth ();
- /* Each interpreter has its own rules on displaying the command
- prompt. */
- if (!current_interp_display_prompt_p ())
- return;
-
old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt);
/* Do not call the python hook on an explicit prompt change as
the above two functions. Calling
rl_callback_handler_remove(), does the job. */
- rl_callback_handler_remove ();
+ gdb_rl_callback_handler_remove ();
do_cleanups (old_chain);
return;
}
if (async_command_editing_p)
{
- rl_callback_handler_remove ();
- rl_callback_handler_install (actual_gdb_prompt, input_handler);
+ gdb_rl_callback_handler_remove ();
+ gdb_rl_callback_handler_install (actual_gdb_prompt);
}
/* new_prompt at this point can be the top of the stack or the one
passed in. It can't be NULL. */
quit_command ((char *) 0, stdin == instream);
}
else
- (*call_readline) (client_data);
+ {
+ do
+ {
+ call_stdin_event_handler_again_p = 0;
+ (*call_readline) (client_data);
+ } while (call_stdin_event_handler_again_p != 0);
+ }
}
/* Re-enable stdin after the end of an execution command in
{
linelength = 80;
linebuffer = (char *) xmalloc (linelength);
+ linebuffer[0] = '\0';
}
p = linebuffer;
*p = 0;
/* Add line to history if appropriate. */
- if (instream == stdin
- && ISATTY (stdin) && *linebuffer)
- add_history (linebuffer);
+ if (*linebuffer && input_from_terminal_p ())
+ gdb_add_history (linebuffer);
/* Note: lines consisting solely of comments are added to the command
history. This is useful when you type a command, and then
sigint_token =
create_async_signal_handler (async_request_quit, NULL);
signal (SIGTERM, handle_sigterm);
+ async_sigterm_token
+ = create_async_signal_handler (async_sigterm_handler, NULL);
/* If SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
to the inferior and breakpoints will be ignored. */
sigtstp_token =
create_async_signal_handler (async_stop_sig, NULL);
#endif
-
}
/* Tell the event loop what to do if SIGINT is received.
gdb_call_async_signal_handler (sigint_token, immediate_quit);
}
+/* Handle GDB exit upon receiving SIGTERM if target_can_async_p (). */
+
+static void
+async_sigterm_handler (gdb_client_data arg)
+{
+ quit_force (NULL, stdin == instream);
+}
+
+/* See defs.h. */
+volatile int sync_quit_force_run;
+
/* Quit GDB if SIGTERM is received.
GDB would quit anyway, but this way it will clean up properly. */
void
handle_sigterm (int sig)
{
signal (sig, handle_sigterm);
- quit_force ((char *) 0, stdin == instream);
+
+ sync_quit_force_run = 1;
+ set_quit_flag ();
+
+ mark_async_signal_handler (async_sigterm_token);
}
/* Do the quit. All the checks have been done by the caller. */
static void
async_disconnect (gdb_client_data arg)
{
- volatile struct gdb_exception exception;
- TRY_CATCH (exception, RETURN_MASK_ALL)
+ TRY
{
quit_cover ();
}
- if (exception.reason < 0)
+ CATCH (exception, RETURN_MASK_ALL)
{
fputs_filtered ("Could not kill the program being debugged",
gdb_stderr);
exception_print (gdb_stderr, exception);
}
+ END_CATCH
- TRY_CATCH (exception, RETURN_MASK_ALL)
+ TRY
{
pop_all_targets ();
}
+ CATCH (exception, RETURN_MASK_ALL)
+ {
+ }
+ END_CATCH
signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */
raise (SIGHUP);
gdb_stdtargerr = NULL;
#endif
- rl_callback_handler_remove ();
+ gdb_rl_callback_handler_remove ();
delete_file_handler (input_fd);
}