From xemacs-m  Tue Apr 22 01:15:09 1997
Received: from crystal.WonderWorks.COM (crystal.WonderWorks.com [192.203.206.1])
	by xemacs.org (8.8.5/8.8.5) with ESMTP id BAA05861
	for <xemacs-beta@xemacs.org>; Tue, 22 Apr 1997 01:15:06 -0500 (CDT)
Received: by crystal.WonderWorks.COM 
	id QQcmig29344; Tue, 22 Apr 1997 01:35:59 -0400 (EDT)
Date: Tue, 22 Apr 1997 01:35:59 -0400 (EDT)
Message-Id: <QQcmig29344.199704220535@crystal.WonderWorks.COM>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
From: Kyle Jones <kyle_jones@wonderworks.com>
To: xemacs-beta@xemacs.org
Subject: [PATCH] 20.2-b1: patch for menubar :filter crash
X-Mailer: VM 6.28 under 19.15 XEmacs Lucid
X-Face: /cA45WHG7jWq>(O3&Z57Y<"WsX5ddc,4c#w0F*zrV#=M
        0@~@,s;b,aMtR5Sqs"+nU.z^CSFQ9t`z2>W,S,]:[+2^
        Nbf6v4g>!&,7R4Ot4Wg{&tm=WX7P["9%a)_da48-^tGy
        ,qz]Z,Zz\{E.,]'EO+F)@$KtF&V

After much fiddling, I think the menu code itself can be fixed to
not croak if reentered, but until that is done this will stop the
crashes.

Tue Apr 22 01:32:00 1997  Kyle Jones  <kyle@crystal.WonderWorks.COM>

	* src/menubar-x.c (pre_activate_hook):
	  set in_menu_callback around call to call to
          menu_item_descriptor_to_widget_value.

	* src/event-stream.c (Fnext_event):
	  signal error if in_menu_callback non-nil to avoid
	  reentering the menubar code and causing a crash later.

	* src/cmdloop.c (command_loop_3):
	  signal error if in_menu_callback non-nil to avoid
	  inflooping calling Fnext_event, which will signal an
	  error if the situation is not caught earlier.


===================================================================
RCS file: src/cmdloop.c,v
retrieving revision 1.1
diff -u -r1.1 src/cmdloop.c
--- 1.1	1997/04/22 03:44:14
+++ src/cmdloop.c	1997/04/22 05:11:35
@@ -216,6 +216,26 @@
 static DOESNT_RETURN
 command_loop_3 (void)
 {
+#ifdef LWLIB_MENUBARS_LUCID
+  extern int in_menu_callback;  /* defined in menubar-x.c */
+#endif /* LWLIB_MENUBARS_LUCID */
+
+#ifdef LWLIB_MENUBARS_LUCID
+  /*
+   * #### Fix the menu code so this isn't necessary.
+   *
+   * We cannot allow the lwmenu code to be reentered, because the
+   * code is not written to be reentrant and will crash.  Therefore
+   * paths from the menu callbacks back into the menu code have to
+   * be blocked.  Fnext_event is the normal path into the menu code,
+   * but waiting to signal an error there is too late in case where
+   * a new command loop has been started.  The error will be caught
+   * and Fnext_event will be called again, looping forever.  So we
+   * signal an error here to avoid the loop.
+   */
+  if (in_menu_callback)
+    error ("Attempt to enter command_loop_3 inside menu callback");
+#endif /* LWLIB_MENUBARS_LUCID */
   /* This function can GC */
   for (;;)
     {
===================================================================
RCS file: src/event-stream.c,v
retrieving revision 1.1
diff -u -r1.1 src/event-stream.c
--- 1.1	1997/04/22 02:43:06
+++ src/event-stream.c	1997/04/22 05:11:37
@@ -1989,10 +1989,27 @@
     XCOMMAND_BUILDER (con->command_builder);
   int store_this_key = 0;
   struct gcpro gcpro1;
-  GCPRO1 (event);
+#ifdef LWLIB_MENUBARS_LUCID
+  extern int in_menu_callback;  /* defined in menubar-x.c */
+#endif /* LWLIB_MENUBARS_LUCID */
 
+  GCPRO1 (event);
   /* DO NOT do QUIT anywhere within this function or the functions it calls.
      We want to read the ^G as an event. */
+
+#ifdef LWLIB_MENUBARS_LUCID
+  /*
+   * #### Fix the menu code so this isn't necessary.
+   *
+   * We cannot allow the lwmenu code to be reentered, because the
+   * code is not written to be reentrant and will crash.  Therefore
+   * paths from the menu callbacks back into the menu code have to
+   * be blocked.  Fnext_event is the normal path into the menu code,
+   * so we signal an error here.
+   */
+  if (in_menu_callback)
+    error ("Attempt to call next-event inside menu callback");
+#endif /* LWLIB_MENUBARS_LUCID */
 
   if (NILP (event))
     event = Fmake_event ();
===================================================================
RCS file: src/menubar-x.c,v
retrieving revision 1.1
diff -u -r1.1 src/menubar-x.c
--- 1.1	1997/04/22 02:18:03
+++ src/menubar-x.c	1997/04/22 05:30:35
@@ -308,6 +308,17 @@
 }
 
 
+#ifdef LWLIB_MENUBARS_LUCID
+int in_menu_callback;
+
+void
+restore_in_menu_callback(Lisp_Object val)
+{
+    in_menu_callback = XINT(val);
+}
+#endif /* LWLIB_MENUBARS_LUCID */
+
+
 /* The order in which callbacks are run is funny to say the least.
    It's sometimes tricky to avoid running a callback twice, and to
    avoid returning prematurely.  So, this function returns true
@@ -338,6 +349,7 @@
   Lisp_Object rest = Qnil;
   Lisp_Object frame;
   int any_changes = 0;
+  int count;
 
   if (!f)
     f = x_any_window_to_frame (d, XtWindow (XtParent (widget)));
@@ -357,8 +369,22 @@
 
       assert (hack_wv->type == INCREMENTAL_TYPE);
       VOID_TO_LISP (submenu_desc, hack_wv->call_data);
+
+      /*
+       * #### Fix the menu code so this isn't necessary.
+       *
+       * Protect against reentering the menu code otherwise we will
+       * crash later when the code gets confused at the state
+       * changes.
+       */
+      count = specpdl_depth ();
+      record_unwind_protect (restore_in_menu_callback,
+			     make_int (in_menu_callback));
+      in_menu_callback = 1;
       wv = menu_item_descriptor_to_widget_value (submenu_desc, SUBMENU_TYPE,
 						 1, 0);
+      unbind_to (count, Qnil);
+
       if (!wv)
 	{
 	  wv = xmalloc_widget_value ();

