[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#7190: Crash in menus on w32
From: |
grischka |
Subject: |
bug#7190: Crash in menus on w32 |
Date: |
Thu, 21 Oct 2010 13:11:25 +0200 |
User-agent: |
Thunderbird 2.0.0.23 (Windows/20090812) |
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
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);
/* 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);
- bug#7190: Crash in menus on w32, (continued)
bug#7190: Crash in menus on w32, grischka, 2010/10/13
bug#7190: Crash in menus on w32,
grischka <=