2007-06-26 Jan Kratochvil * top.c (gdb_readline_wrapper) Wrap readline() by readline_cleanup(). (readline_cleanup): New function. 2007-06-26 Jan Kratochvil H.J. Lu PR tui/2173 * readline.c (readline): Save/restore RL_STATE_CALLBACK into STATE_LIST. (rl_readline_unwind, struct state, state_list): New. * readline.h (rl_readline_unwind): New declaration. 2007-06-26 Jan Kratochvil * rltech.texi (Readline Signal Handling): Describe rl_readline_unwind(). --- sources-unpatched/gdb/top.c 2007-06-26 13:04:11.000000000 +0200 +++ sources/gdb/top.c 2007-06-26 12:38:43.000000000 +0200 @@ -706,6 +706,13 @@ The filename in which to record the comm value); } +static void +readline_cleanup (void *unused) +{ + /* No need to check for it by autoconf as libreadline is bundled with GDB. */ + rl_readline_unwind (); +} + /* This is like readline(), but it has some gdb-specific behavior. gdb can use readline in both the synchronous and async modes during a single gdb invocation. At the ordinary top-level prompt we might @@ -719,6 +726,9 @@ The filename in which to record the comm char * gdb_readline_wrapper (char *prompt) { + char *retval; + struct cleanup *cleanups; + /* Set the hook that works in this case. */ if (after_char_processing_hook) { @@ -726,7 +736,11 @@ gdb_readline_wrapper (char *prompt) after_char_processing_hook = NULL; } - return readline (prompt); + cleanups = make_cleanup (readline_cleanup, NULL); + retval = readline (prompt); + discard_cleanups (cleanups); + + return retval; } --- sources-unpatched/readline/doc/rltech.texi 2007-06-26 12:54:57.000000000 +0200 +++ sources/readline/doc/rltech.texi 2007-06-26 12:40:50.000000000 +0200 @@ -1336,7 +1336,16 @@ resetting the terminal to its original s handler does more than update its idea of the terminal size and return (for example, a @code{longjmp} back to a main processing loop), it @emph{must} call @code{rl_cleanup_after_signal()} (described below), to restore the -terminal state. +terminal state. Each @code{longjmp} call must be also protected by +@code{rl_readline_unwind()}: + +@deftypefun void rl_readline_unwind (void) +Each @code{readline()} call you jump out of by @code{longjmp} must be matched +by one call of this function. It is appropriate to call it from your +@code{catch} part of the C++ exception handler. This functiona must not be +called if @code{readline()} returns itself. If you do not abort +@code{readline()} by @code{longjmp} you must never call this function. +@end deftypefun Readline provides two variables that allow application writers to control whether or not it will catch certain signals and act on them --- sources-unpatched/readline/readline.c 2007-06-26 12:54:52.000000000 +0200 +++ sources/readline/readline.c 2007-06-26 12:33:57.000000000 +0200 @@ -287,7 +287,27 @@ rl_set_prompt (prompt) rl_visible_prompt_length = rl_expand_prompt (rl_prompt); return 0; } - + +struct state { + struct state *next; + int in_callback; +}; +static struct state *state_list; + +/* To be called once for each readline () call which you have jumped out of by + longjmp() or siglongjmp(). Function needs to be called BEFORE the jump. */ +void +rl_readline_unwind () +{ + /* NULL should not happen. */ + if (state_list != NULL) + { + if (state_list->in_callback) + RL_SETSTATE (RL_STATE_CALLBACK); + state_list = state_list->next; + } +} + /* Read a line of input. Prompt with PROMPT. An empty PROMPT means none. A return value of NULL means that EOF was encountered. */ char * @@ -295,6 +315,7 @@ readline (prompt) const char *prompt; { char *value; + struct state state; /* If we are at EOF return a NULL string. */ if (rl_pending_input == EOF) @@ -303,6 +324,15 @@ readline (prompt) return ((char *)NULL); } + /* When we call readline, we have to make sure that readline isn't in + the callback state. Otherwise, it will get really confused. + PR gdb tui/2173. */ + state.next = state_list; + state_list = &state; + state.in_callback = RL_ISSTATE (RL_STATE_CALLBACK); + if (state.in_callback) + RL_UNSETSTATE (RL_STATE_CALLBACK); + rl_set_prompt (prompt); rl_initialize (); @@ -321,6 +351,8 @@ readline (prompt) rl_clear_signals (); #endif + rl_readline_unwind (); + return (value); } --- sources-unpatched/readline/readline.h 2007-06-26 12:54:52.000000000 +0200 +++ sources/readline/readline.h 2007-06-26 12:34:00.000000000 +0200 @@ -280,6 +280,10 @@ extern int rl_vi_eword PARAMS((int, int) /* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */ extern char *readline PARAMS((const char *)); +/* To be called once for each readline () call which you have jumped out of by + longjmp() or siglongjmp(). Function needs to be called BEFORE the jump. */ +extern void rl_readline_unwind PARAMS((void)); + extern int rl_set_prompt PARAMS((const char *)); extern int rl_expand_prompt PARAMS((char *));