changeset 83374:0b75ace4f7ad

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
author Karoly Lorentey <lorentey@elte.hu>
date Sun, 11 Sep 2005 06:42:03 +0000
parents 35ba943c8399
children 6e8cc0cd2f5a
files README.multi-tty src/Makefile.in src/callint.c src/data.c src/fns.c src/keyboard.c src/keyboard.h src/minibuf.c src/xdisp.c
diffstat 9 files changed, 115 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/README.multi-tty	Sun Sep 11 04:10:45 2005 +0000
+++ b/README.multi-tty	Sun Sep 11 06:42:03 2005 +0000
@@ -31,27 +31,28 @@
 contributed to the project by testing, submitting patches, bug
 reports, and suggestions.  Thanks!
 
-ARISAWA Akihiro <ari at mbf dot ocn dot ne dot jp>
-Vincent Bernat <bernat at luffy dot cx>
-Han Boetes <han at mijncomputer dot nl>
-Robert J. Chassell <bob at rattlesnake dot com>
-Romain Francoise <romain at orebokech dot com>
-Ami Fischman <ami at fischman dot org>
-Friedrich Delgado Friedrichs <friedel at nomaden dot org>
-IRIE Tetsuya <irie at t dot email dot ne dot jp>
-Yoshiaki Kasahara <kasahara at nc dot kyushu-u dot ac dot jp>
-Bas Kok <nekkobassu at yahoo dot com>
-Jurej Kubelka <Juraj dot Kubelka at email dot cz>
-David Lichteblau <david at lichteblau dot com>
-Xavier Mallard <zedek at gnu-rox dot org>
-Istvan Marko <mi-mtty at kismala dot com>
-Ted Morse <morse at ciholas dot com>
-Dan Nicolaescu <dann at ics dot uci dot edu>
-Gergely Nagy <algernon at debian dot org>
-Mark Plaksin <happy at mcplaksin dot org>
-Francisco Borges <borges at let dot rug dot nl>
-Frank Ruell <stoerte at dreamwarrior dot net>
-Dan Waber <dwaber at logolalia dot com>
+ARISAWA Akihiro <ari@mbf.ocn.ne.jp>
+Vincent Bernat <bernat@luffy.cx>
+Han Boetes <han@mijncomputer.nl>
+Robert J. Chassell <bob@rattlesnake.com>
+Romain Francoise <romain@orebokech.com>
+Ami Fischman <ami@fischman.org>
+Friedrich Delgado Friedrichs <friedel@nomaden.org>
+IRIE Tetsuya <irie@t.email.ne.jp>
+Yoshiaki Kasahara <kasahara@nc.kyushu-u.ac.jp>
+Bas Kok <nekkobassu@yahoo.com>
+Jurej Kubelka <Juraj.Kubelka@email.cz>
+David Lichteblau <david@lichteblau.com>
+Xavier Mallard <zedek@gnu-rox.org>
+Istvan Marko <mi-mtty@kismala.com>
+Ted Morse <morse@ciholas.com>
+Gergely Nagy <algernon@debian.org>
+Dan Nicolaescu <dann@ics.uci.edu>
+Kalle Olavi Niemitalo <kon@iki.fi>
+Mark Plaksin <happy@mcplaksin.org>
+Francisco Borges <borges@let.rug.nl>
+Frank Ruell <stoerte@dreamwarrior.net>
+Dan Waber <dwaber@logolalia.com>
 and many others.
 
 Richard Stallman was kind enough to review an earlier version of my
@@ -387,17 +388,8 @@
 THINGS TO DO
 ------------
 
-** This long-standing bug (first reported by Han Boetes) seems to come
-   and go all the time.  It is time to track it down and fix it.
-
-	emacs
-		M-x server-start
-	
-	# From another xterm:
-	emacsclient -e '(y-or-n-p "Do you want me to crash? ")'
-		# Notice how the answer ends up in the *scratch* buffer
-		M-x garbage-collect
-		SIGSEGV
+** Report GTK multi-display problems to GTK maintainers.  For extra
+   credit, fix them.
 
 ** frames-on-display-list should also accept frames.
 
@@ -1239,5 +1231,19 @@
 
    (I think patch-370 fixed this.)
 
+-- This long-standing bug (first reported by Han Boetes) seems to come
+   and go all the time.  It is time to track it down and fix it.
+
+	emacs
+		M-x server-start
+	
+	# From another xterm:
+	emacsclient -e '(y-or-n-p "Do you want me to crash? ")'
+		# Notice how the answer ends up in the *scratch* buffer
+		M-x garbage-collect
+		SIGSEGV
+
+   (Fixed in patch-414 after detailed analysis by Kalle Olavi Niemitalo.)
+
 ;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
 
--- a/src/Makefile.in	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/Makefile.in	Sun Sep 11 06:42:03 2005 +0000
@@ -1213,13 +1213,13 @@
  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
--- a/src/callint.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/callint.c	Sun Sep 11 06:42:03 2005 +0000
@@ -408,8 +408,8 @@
       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 @@
   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;
--- a/src/data.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/data.c	Sun Sep 11 06:42:03 2005 +0000
@@ -30,6 +30,7 @@
 #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 <float.h>
@@ -1891,9 +1892,9 @@
 {
   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 @@
 {
   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;
 }
 
--- a/src/fns.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/fns.c	Sun Sep 11 06:42:03 2005 +0000
@@ -48,6 +48,7 @@
 #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 @@
 	  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;
--- a/src/keyboard.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/keyboard.c	Sun Sep 11 06:42:03 2005 +0000
@@ -1034,24 +1034,19 @@
      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;
-{
-  if (BUFFERP (XCAR (info)))
-    Fset_buffer (XCAR (info));
-
-  if (NILP (XCDR (info)))
-    any_kboard_state ();
-  else
-    single_kboard_state ();
+recursive_edit_unwind (buffer)
+     Lisp_Object buffer;
+{
+  if (BUFFERP (buffer))
+    Fset_buffer (buffer);
 
   command_loop_level--;
   update_mode_lines = 1;
@@ -1116,8 +1111,8 @@
 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 @@
   p->kboard = current_kboard;
   kboard_stack = p;
 
-  current_kboard = d->kboard;
+  current_kboard = k;
 #endif
 }
 
@@ -1135,20 +1130,11 @@
 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 @@
   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 @@
 	{
 	  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 @@
 	      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.  */
 	    }
--- a/src/keyboard.h	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/keyboard.h	Sun Sep 11 06:42:03 2005 +0000
@@ -319,9 +319,11 @@
 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));
--- a/src/minibuf.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/minibuf.c	Sun Sep 11 06:42:03 2005 +0000
@@ -467,7 +467,6 @@
 
   specbind (Qminibuffer_default, defalt);
 
-  single_kboard_state ();
 #ifdef HAVE_X_WINDOWS
   if (display_hourglass_p)
     cancel_hourglass ();
@@ -551,6 +550,8 @@
   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.  */
 
--- a/src/xdisp.c	Sun Sep 11 04:10:45 2005 +0000
+++ b/src/xdisp.c	Sun Sep 11 06:42:03 2005 +0000
@@ -15888,7 +15888,7 @@
      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 @@
 
   push_frame_kboard (it.f);
   display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
-  pop_frame_kboard ();
+  pop_kboard ();
 
   if (no_props)
     {