all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: grischka <grishka@gmx.de>
To: lennart.borgman@gmail.com
Cc: bug-gnu-emacs@gnu.org
Subject: bug#7190: Crash in menus on w32
Date: Thu, 21 Oct 2010 13:11:25 +0200	[thread overview]
Message-ID: <4CC01FDD.5060707@gmx.de> (raw)
In-Reply-To: <AANLkTincbDTOEFg2kzZiH3Csh_jdv84uj70=CaRYG9ey@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 369 bytes --]

Here's a patch that fixes the bug.  Actually 4 bugs:
1) the initial cause: was freeing items prematurely and trying to
     free already freed items
2) memory leak: was trying to free items from already deleted menu
3) memory leak: was trying to free menu from already deleted window
4) other: was trying to set cursor in window with no associated frame

--- grischka


[-- Attachment #2: free-menu-strings.diff --]
[-- Type: text/plain, Size: 7179 bytes --]

commit 064225db78640a1fb48b68aac603c8e05cc69b80
Author: grischka <grischka>
Date:   Thu Oct 14 13:23:38 2010 +0200

    fix w32menu ownerdraw string alloc/free

diff --git a/src/w32fns.c b/src/w32fns.c
index 8085035..83d577e 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -76,7 +76,6 @@ extern void free_frame_menubar (struct frame *);
 extern double atof (const char *);
 extern int w32_console_toggle_lock_key (int, Lisp_Object);
 extern void w32_menu_display_help (HWND, HMENU, UINT, UINT);
-extern void w32_free_menu_strings (HWND);
 extern const char *map_w32_filename (const char *, const char **);
 
 extern int quit_char;
@@ -280,12 +279,7 @@ unsigned int msh_mousewheel = 0;
 /* Timers */
 #define MOUSE_BUTTON_ID	1
 #define MOUSE_MOVE_ID	2
-#define MENU_FREE_ID 3
 #define HOURGLASS_ID 4
-/* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
-   is received.  */
-#define MENU_FREE_DELAY 1000
-static unsigned menu_free_timer = 0;
 
 /* In dispnew.c */
 
@@ -3387,21 +3381,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	  KillTimer (hwnd, mouse_move_timer);
 	  mouse_move_timer = 0;
 	}
-      else if (wParam == menu_free_timer)
-	{
-	  KillTimer (hwnd, menu_free_timer);
-	  menu_free_timer = 0;
-	  f = x_window_to_frame (dpyinfo, hwnd);
-          /* If a popup menu is active, don't wipe its strings.  */
-	  if (menubar_in_use
-              && current_popup_menu == NULL)
-	    {
-	      /* Free memory used by owner-drawn and help-echo strings.  */
-	      w32_free_menu_strings (hwnd);
-	      f->output_data.w32->menubar_active = 0;
-              menubar_in_use = 0;
-	    }
-	}
       else if (wParam == hourglass_timer)
 	{
 	  KillTimer (hwnd, hourglass_timer);
@@ -3465,14 +3444,11 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
     case WM_EXITMENULOOP:
       f = x_window_to_frame (dpyinfo, hwnd);
 
-      /* If a menu is still active, check again after a short delay,
-	 since Windows often (always?) sends the WM_EXITMENULOOP
-	 before the corresponding WM_COMMAND message.
-         Don't do this if a popup menu is active, since it is only
-         menubar menus that require cleaning up in this way.
-      */
       if (f && menubar_in_use && current_popup_menu == NULL)
-	menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
+       {
+         f->output_data.w32->menubar_active = 0;
+         menubar_in_use = 0;
+       }
 
       /* If hourglass cursor should be displayed, display it now.  */
       if (f && f->output_data.w32->hourglass_p)
@@ -3632,15 +3608,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       goto command;
     case WM_COMMAND:
       menubar_in_use = 0;
-      f = x_window_to_frame (dpyinfo, hwnd);
-      if (f && HIWORD (wParam) == 0)
-	{
-	  if (menu_free_timer)
-	    {
-	      KillTimer (hwnd, menu_free_timer);
-	      menu_free_timer = 0;
-	    }
-	}
     case WM_MOVE:
     case WM_SIZE:
     command:
@@ -3748,6 +3715,8 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       if (LOWORD (lParam) == HTCLIENT)
 	{
 	  f = x_window_to_frame (dpyinfo, hwnd);
+	  if (!f)
+	    return 0;
 	  if (f->output_data.w32->hourglass_p && !menubar_in_use
 	      && !current_popup_menu)
 	    SetCursor (f->output_data.w32->hourglass_cursor);
diff --git a/src/w32menu.c b/src/w32menu.c
index ff6bd97..78d59fc 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -108,7 +108,7 @@ static Lisp_Object simple_dialog_show (FRAME_PTR, Lisp_Object, Lisp_Object);
 static void utf8to16 (unsigned char *, int, WCHAR *);
 static int fill_in_menu (HMENU, widget_value *);
 
-void w32_free_menu_strings (HWND);
+static void w32_free_menu_strings (HMENU);
 \f
 
 /* This is set nonzero after the user activates the menu bar, and set
@@ -347,8 +347,6 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
 	      buf.kind = MENU_BAR_EVENT;
 	      buf.frame_or_window = frame;
 	      buf.arg = entry;
-	      /* Free memory used by owner-drawn and help-echo strings.  */
-	      w32_free_menu_strings (FRAME_W32_WINDOW (f));
 	      kbd_buffer_store_event (&buf);
 
 	      f->output_data.w32->menubar_active = 0;
@@ -357,8 +355,6 @@ menubar_selection_callback (FRAME_PTR f, void * client_data)
 	  i += MENU_ITEMS_ITEM_LENGTH;
 	}
     }
-  /* Free memory used by owner-drawn and help-echo strings.  */
-  w32_free_menu_strings (FRAME_W32_WINDOW (f));
   f->output_data.w32->menubar_active = 0;
 }
 
@@ -588,6 +584,7 @@ set_frame_menubar (FRAME_PTR f, int first_time, int deep_p)
 
   if (menubar_widget)
     {
+      w32_free_menu_strings (menubar_widget);
       /* Empty current menubar, rather than creating a fresh one.  */
       while (DeleteMenu (menubar_widget, 0, MF_BYPOSITION))
 	;
@@ -643,6 +640,7 @@ free_frame_menubar (FRAME_PTR f)
     HMENU old = GetMenu (FRAME_W32_WINDOW (f));
     SetMenu (FRAME_W32_WINDOW (f), NULL);
     f->output_data.w32->menubar_widget = NULL;
+    w32_free_menu_strings (old);
     DestroyMenu (old);
   }
 
@@ -898,10 +896,11 @@ w32_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
   /* Free the widget_value objects we used to specify the contents.  */
   free_menubar_widget_value_tree (first_wv);
 
+  /* Free the owner-drawn and help-echo menu strings.  */
+  w32_free_menu_strings (menu);
   DestroyMenu (menu);
+  current_popup_menu = NULL;
 
-  /* Free the owner-drawn and help-echo menu strings.  */
-  w32_free_menu_strings (FRAME_W32_WINDOW (f));
   f->output_data.w32->menubar_active = 0;
 
   /* Find the selected item, and its pane, to return
@@ -1651,9 +1650,11 @@ w32_menu_display_help (HWND owner, HMENU menu, UINT item, UINT flags)
 
 /* Free memory used by owner-drawn strings.  */
 static void
-w32_free_submenu_strings (HMENU menu)
+w32_free_menu_strings (HMENU menu)
 {
   int i, num = GetMenuItemCount (menu);
+  if (!get_menu_item_info)
+    return;
   for (i = 0; i < num; i++)
     {
       MENUITEMINFO info;
@@ -1674,29 +1675,10 @@ w32_free_submenu_strings (HMENU menu)
 
       /* Recurse down submenus.  */
       if (info.hSubMenu)
-	w32_free_submenu_strings (info.hSubMenu);
+	w32_free_menu_strings (info.hSubMenu);
     }
 }
 
-void
-w32_free_menu_strings (HWND hwnd)
-{
-  HMENU menu = current_popup_menu;
-
-  if (get_menu_item_info)
-    {
-      /* If there is no popup menu active, free the strings from the frame's
-	 menubar.  */
-      if (!menu)
-	menu = GetMenu (hwnd);
-
-      if (menu)
-	w32_free_submenu_strings (menu);
-    }
-
-  current_popup_menu = NULL;
-}
-
 #endif /* HAVE_MENUS */
 
 /* The following is used by delayed window autoselection.  */
diff --git a/src/w32term.c b/src/w32term.c
index 1f53860..0cef1b7 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5734,11 +5734,11 @@ x_free_frame_resources (struct frame *f)
   if (FRAME_FACE_CACHE (f))
     free_frame_faces (f);
 
+  free_frame_menubar (f);
+
   if (FRAME_W32_WINDOW (f))
     my_destroy_window (f, FRAME_W32_WINDOW (f));
 
-  free_frame_menubar (f);
-
   unload_color (f, FRAME_FOREGROUND_PIXEL (f));
   unload_color (f, FRAME_BACKGROUND_PIXEL (f));
   unload_color (f, f->output_data.w32->cursor_pixel);

  parent reply	other threads:[~2010-10-21 11:11 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-11 15:13 bug#7190: Crash in menus on w32 Lennart Borgman
2010-10-11 19:20 ` Eli Zaretskii
2010-10-11 21:21   ` Lennart Borgman
2010-10-12  4:04     ` Eli Zaretskii
2010-10-12  9:37       ` Lennart Borgman
2010-10-12 19:05         ` Eli Zaretskii
2010-10-12 19:13           ` Lennart Borgman
2010-10-12 19:40             ` Eli Zaretskii
2010-10-12 20:09               ` Lennart Borgman
2010-10-12 20:14                 ` Eli Zaretskii
2010-10-12 20:49                   ` Lennart Borgman
2010-10-13 11:30                     ` Eli Zaretskii
2010-10-19  0:20           ` Lennart Borgman
2010-10-19  5:59             ` Eli Zaretskii
2010-10-19 10:33               ` Lennart Borgman
2010-10-13 11:02 ` grischka
2010-10-13 11:08   ` Lennart Borgman
2010-10-13 14:03     ` grischka
2010-10-13 14:43       ` Lennart Borgman
2010-10-13 15:51         ` grischka
2010-10-13 16:06           ` Lennart Borgman
2010-10-21 11:11 ` grischka [this message]
2010-10-21 15:27   ` Jason Rumney
2010-10-21 17:07     ` grischka
2010-10-22 14:09       ` Jason Rumney
2010-10-22 16:20         ` grischka
2010-11-08  1:49           ` Lennart Borgman
2010-11-08 10:15             ` grischka
2010-11-08 11:18               ` Lennart Borgman
2010-11-08 19:51                 ` grischka
2010-11-08 23:11                   ` Lennart Borgman
2010-11-09 16:16                     ` grischka
2010-11-09 17:08                       ` Eli Zaretskii
2010-11-09 18:39                         ` grischka
     [not found]                           ` <jwvpqueyy9i.fsf-monnier+emacs@gnu.org>
2010-11-10 10:33                             ` grischka
2010-11-12  7:53 ` Glenn Morris
2010-11-12 22:40   ` grischka
2010-11-13 17:08     ` Chong Yidong
2013-02-18  2:23       ` Glenn Morris
2013-02-18  2:39         ` Lennart Borgman
2013-02-18  3:43         ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4CC01FDD.5060707@gmx.de \
    --to=grishka@gmx.de \
    --cc=bug-gnu-emacs@gnu.org \
    --cc=lennart.borgman@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.