From 256c9c3a61a5a2c5d394277f5b0f25adb453771d Mon Sep 17 00:00:00 2001 From: Karoly Lorentey Date: Sun, 11 Sep 2005 06:42:03 +0000 Subject: Fix crash after y-or-n-p prompt triggered by emacsclient. (Reported by Han Boetes, analysis by Kalle Olavi Niemitalo.) * src/keyboard.c (temporarily_switch_to_single_kboard) (record_single_kboard_state, restore_kboard_configuration): New functions. (timer_check): Use record_single_kboard_state instead of naive single_kboard state management. * src/fns.c: Include termhooks.h. (Fy_or_n_p): Use temporarily_switch_to_single_kboard to prevent crashes caused by bogus longjmps in read_char. * src/callint.c (Fcall_interactively): Use temporarily_switch_to_single_kboard instead of single_kboard_state. Make sure it is correctly unwinded. * src/keyboard.c (recursive_edit_unwind): Remove single_kboard stuff. (Frecursive_edit): Use temporarily_switch_to_single_kboard for single_kboard state management. * src/minibuf.c (read_minibuf): Use temporarily_switch_to_single_kboard instead of simply calling single_kboard_state. * src/keyboard.c (push_device_kboard): Remove function. (push_kboard): New function. (push_frame_kboard): Use it. (pop_frame_kboard): Rename to pop_kboard. * src/xdisp.c (display_mode_line, Fformat_mode_line): Update uses. * src/data.c: Include termhooks.h. (Fterminal_local_value, Fset_terminal_local_value): Update. * src/Makefile.in (data.o, fns.o): Add termhooks.h dependency. * src/keyboard.h (push_device_kboard, pop_frame_kboard): Remove declarations. (push_kboard, pop_kboard, temporarily_switch_to_single_kboard) (record_single_kboard_state): New declarations. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-414 --- src/Makefile.in | 4 +-- src/callint.c | 6 ++-- src/data.c | 9 +++--- src/fns.c | 3 ++ src/keyboard.c | 85 +++++++++++++++++++++++++++++++++++++-------------------- src/keyboard.h | 6 ++-- src/minibuf.c | 3 +- src/xdisp.c | 4 +-- 8 files changed, 76 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/Makefile.in b/src/Makefile.in index 2e4b4f6ad7..fdeeb544b1 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1213,13 +1213,13 @@ alloc.o: alloc.c process.h frame.h window.h buffer.h puresize.h syssignal.h key blockinput.h atimer.h systime.h charset.h dispextern.h $(config_h) $(INTERVAL_SRC) bytecode.o: bytecode.c buffer.h syntax.h charset.h window.h dispextern.h \ frame.h xterm.h $(config_h) -data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h frame.h $(config_h) +data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h frame.h termhooks.h $(config_h) eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h \ dispextern.h $(config_h) floatfns.o: floatfns.c $(config_h) fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ keymap.h frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h \ - blockinput.h xterm.h + blockinput.h xterm.h termhooks.h print.o: print.c process.h frame.h window.h buffer.h keyboard.h charset.h \ $(config_h) dispextern.h termchar.h $(INTERVAL_SRC) msdos.h composite.h \ termchar.h diff --git a/src/callint.c b/src/callint.c index 5979e495ac..d44d2f20ca 100644 --- a/src/callint.c +++ b/src/callint.c @@ -408,8 +408,8 @@ If KEYS is omitted or nil, the return value of `this-command-keys' is used. */) real_this_command= save_real_this_command; current_kboard->Vlast_command = save_last_command; - single_kboard_state (); - return apply1 (function, specs); + temporarily_switch_to_single_kboard (NULL); + return unbind_to (speccount, apply1 (function, specs)); } /* Here if function specifies a string to control parsing the defaults */ @@ -875,7 +875,7 @@ If KEYS is omitted or nil, the return value of `this-command-keys' is used. */) real_this_command= save_real_this_command; current_kboard->Vlast_command = save_last_command; - single_kboard_state (); + temporarily_switch_to_single_kboard (NULL); { Lisp_Object val; diff --git a/src/data.c b/src/data.c index b187a3e748..b024511d77 100644 --- a/src/data.c +++ b/src/data.c @@ -30,6 +30,7 @@ Boston, MA 02110-1301, USA. */ #include "keyboard.h" #include "frame.h" #include "syssignal.h" +#include "termhooks.h" /* For FRAME_KBOARD reference in y-or-n-p. */ #ifdef STDC_HEADERS #include @@ -1891,9 +1892,9 @@ selected frame's display device). */) { Lisp_Object result; struct device *d = get_device (device, 1); - push_device_kboard (d); + push_kboard (d->kboard); result = Fsymbol_value (symbol); - pop_frame_kboard (); + pop_kboard (); return result; } @@ -1911,9 +1912,9 @@ selected frame's display device). */) { Lisp_Object result; struct device *d = get_device (device, 1); - push_device_kboard (d); + push_kboard (d->kboard); result = Fset (symbol, value); - pop_frame_kboard (); + pop_kboard (); return result; } diff --git a/src/fns.c b/src/fns.c index 987762a1f4..2e2e575911 100644 --- a/src/fns.c +++ b/src/fns.c @@ -48,6 +48,7 @@ Boston, MA 02110-1301, USA. */ #include "frame.h" #include "window.h" #include "blockinput.h" +#include "termhooks.h" /* For display->kboard reference in terminal-local-value. */ #if defined (HAVE_MENUS) && defined (HAVE_X_WINDOWS) #include "xterm.h" #endif @@ -3307,7 +3308,9 @@ is nil and `use-dialog-box' is non-nil. */) Fraise_frame (mini_frame); } + temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ())); obj = read_filtered_event (1, 0, 0, 0); + cursor_in_echo_area = 0; /* If we need to quit, quit with cursor_in_echo_area = 0. */ QUIT; diff --git a/src/keyboard.c b/src/keyboard.c index 74f8d7d51e..14dd4e33c8 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1034,24 +1034,19 @@ This function is called by the editor initialization to begin editing. */) like it is done in the splash screen display, we have to make sure that we restore single_kboard as command_loop_1 would have done if it were left normally. */ - record_unwind_protect (recursive_edit_unwind, - Fcons (buffer, single_kboard ? Qt : Qnil)); + temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ())); + record_unwind_protect (recursive_edit_unwind, buffer); recursive_edit_1 (); return unbind_to (count, Qnil); } Lisp_Object -recursive_edit_unwind (info) - Lisp_Object info; +recursive_edit_unwind (buffer) + Lisp_Object buffer; { - if (BUFFERP (XCAR (info))) - Fset_buffer (XCAR (info)); - - if (NILP (XCDR (info))) - any_kboard_state (); - else - single_kboard_state (); + if (BUFFERP (buffer)) + Fset_buffer (buffer); command_loop_level--; update_mode_lines = 1; @@ -1116,8 +1111,8 @@ struct kboard_stack static struct kboard_stack *kboard_stack; void -push_device_kboard (d) - struct device *d; +push_kboard (k) + struct kboard *k; { #ifdef MULTI_KBOARD struct kboard_stack *p @@ -1127,7 +1122,7 @@ push_device_kboard (d) p->kboard = current_kboard; kboard_stack = p; - current_kboard = d->kboard; + current_kboard = k; #endif } @@ -1135,20 +1130,11 @@ void push_frame_kboard (f) FRAME_PTR f; { -#ifdef MULTI_KBOARD - struct kboard_stack *p - = (struct kboard_stack *) xmalloc (sizeof (struct kboard_stack)); - - p->next = kboard_stack; - p->kboard = current_kboard; - kboard_stack = p; - - current_kboard = FRAME_KBOARD (f); -#endif + push_kboard (f->device->kboard); } void -pop_frame_kboard () +pop_kboard () { #ifdef MULTI_KBOARD struct kboard_stack *p = kboard_stack; @@ -1157,6 +1143,46 @@ pop_frame_kboard () xfree (p); #endif } + +/* Switch to single_kboard mode. If K is non-nil, set it as the + current keyboard. Use record_unwind_protect to return to the + previous state later. */ + +void +temporarily_switch_to_single_kboard (k) + struct kboard *k; +{ +#ifdef MULTI_KBOARD + int was_locked = single_kboard; + if (k != NULL) + push_kboard (k); + else + push_kboard (current_kboard); + single_kboard_state (); + record_unwind_protect (restore_kboard_configuration, + (was_locked ? Qt : Qnil)); +#endif +} + +void +record_single_kboard_state () +{ + push_kboard (current_kboard); + record_unwind_protect (restore_kboard_configuration, + (single_kboard ? Qt : Qnil)); +} + +static Lisp_Object +restore_kboard_configuration (was_locked) + Lisp_Object was_locked; +{ + pop_kboard (); + if (NILP (was_locked)) + any_kboard_state (); + else + single_kboard_state (); + return Qnil; +} /* Handle errors that are not handled at inner levels by printing an error message and returning to the editor command loop. */ @@ -4472,10 +4498,13 @@ timer_check (do_it_now) { if (NILP (vector[0])) { - int was_locked = single_kboard; int count = SPECPDL_INDEX (); Lisp_Object old_deactivate_mark = Vdeactivate_mark; + /* On unbind_to, resume allowing input from any kboard, if that + was true before. */ + record_single_kboard_state (); + /* Mark the timer as triggered to prevent problems if the lisp code fails to reschedule it right. */ vector[0] = Qt; @@ -4487,10 +4516,6 @@ timer_check (do_it_now) timers_run++; unbind_to (count, Qnil); - /* Resume allowing input from any kboard, if that was true before. */ - if (!was_locked) - any_kboard_state (); - /* Since we have handled the event, we don't need to tell the caller to wake up and do it. */ } diff --git a/src/keyboard.h b/src/keyboard.h index 0063922787..690cb9cb17 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -319,9 +319,11 @@ extern void init_kboard P_ ((KBOARD *)); extern void delete_kboard P_ ((KBOARD *)); extern void single_kboard_state P_ ((void)); extern void not_single_kboard_state P_ ((KBOARD *)); -extern void push_device_kboard P_ ((struct device *)); +extern void push_kboard P_ ((struct kboard *)); extern void push_frame_kboard P_ ((struct frame *)); -extern void pop_frame_kboard P_ ((void)); +extern void pop_kboard P_ ((void)); +extern void temporarily_switch_to_single_kboard P_ ((struct kboard *)); +extern void record_single_kboard_state P_ ((void)); extern void record_asynch_buffer_change P_ ((void)); extern SIGTYPE input_poll_signal P_ ((int)); extern void start_polling P_ ((void)); diff --git a/src/minibuf.c b/src/minibuf.c index 8f07a4603c..a66d0f8f5c 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -467,7 +467,6 @@ read_minibuf (map, initial, prompt, backup_n, expflag, specbind (Qminibuffer_default, defalt); - single_kboard_state (); #ifdef HAVE_X_WINDOWS if (display_hourglass_p) cancel_hourglass (); @@ -551,6 +550,8 @@ read_minibuf (map, initial, prompt, backup_n, expflag, if (minibuffer_auto_raise) Fraise_frame (mini_frame); + temporarily_switch_to_single_kboard (XFRAME (mini_frame)->device->kboard); + /* We have to do this after saving the window configuration since that is what restores the current buffer. */ diff --git a/src/xdisp.c b/src/xdisp.c index bc016fb7c7..c8ca187f3d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -15888,7 +15888,7 @@ display_mode_line (w, face_id, format) values. */ push_frame_kboard (it.f); display_mode_element (&it, 0, 0, 0, format, Qnil, 0); - pop_frame_kboard (); + pop_kboard (); unbind_to (count, Qnil); @@ -16551,7 +16551,7 @@ are the selected window and the window's buffer). */) push_frame_kboard (it.f); display_mode_element (&it, 0, 0, 0, format, Qnil, 0); - pop_frame_kboard (); + pop_kboard (); if (no_props) { -- cgit v1.2.3