* NT Emacs crashes when selecting a menubar item
@ 2002-07-24 18:55 David Ponce
2002-07-25 18:07 ` Richard Stallman
0 siblings, 1 reply; 13+ messages in thread
From: David Ponce @ 2002-07-24 18:55 UTC (permalink / raw)
Hi All,
Sometimes when I select an item on the menu bar Emacs crashes because
it try to access a bad memory location. Sometimes also this even
crashes Windows NT because of a page fault!
I managed to get a backtrace (see at end) using Dr. Mingw, a
Just-In-Time debugger. It shows that the problem occurs in the
function `free_menubar_widget_value_tree' which try to free a
corrupted `widget_value' data structure. Would it be possible that
the GC corrupted it? Unfortunately, I don't know enough the Emacs
internals to give more useful informations :-(
What I can say is that the problem seems to occur when I use complex
imenu indexes (generated by Semantic). Also sometimes I noticed that
I got garbaged imenu item names.
Hope this will help.
David
In GNU Emacs 21.3.50.1 (i386-mingw-nt4.0.1381)
of 2002-07-24 on EBAT311
configured using `configure --with-gcc (2.95)'
Important settings:
value of $LC_ALL: nil
value of $LC_COLLATE: nil
value of $LC_CTYPE: nil
value of $LC_MESSAGES: nil
value of $LC_MONETARY: nil
value of $LC_NUMERIC: nil
value of $LC_TIME: nil
value of $LANG: ENU
locale-coding-system: iso-latin-1
default-enable-multibyte-characters: t
------------- Dr. Mingw backtrace
emacs.exe caused an Access Violation at location 01110446 in module
emacs.exe Reading from location 63746189.
Registers:
eax=6374616d ebx=6374616d ecx=0082ffe0 edx=0fe8007a esi=00000020
edi=11555c04
eip=01110446 esp=0082f3e8 ebp=0082f400 iopl=0 nv up ei pl nz na
pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000
efl=00000202
Call stack:
01110446 emacs.exe:01110446 free_menubar_widget_value_tree w32menu.c:1081
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = ,
char * value = ,
char * key = ,
int help = ,
Boolean enabled = ,
Boolean selected = ,
enum button_type button_type = ,
Boolean title = ,
struct _widget_value * contents = ,
XtPointer call_data = ,
struct _widget_value * next =
}
)
...
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
> if (wv->contents && (wv->contents != (widget_value*)1))
{
free_menubar_widget_value_tree (wv->contents);
...
0111046B emacs.exe:0111046B free_menubar_widget_value_tree w32menu.c:1084
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 875524,
Boolean enabled = 'H',
Boolean selected = 'i',
enum button_type button_type = 1751607660,
Boolean title = 't',
struct _widget_value * contents = 0x6374616d,
XtPointer call_data = 0x20646568,
struct _widget_value * next = 0x746e7953
}
)
...
{
free_menubar_widget_value_tree (wv->contents);
> wv->contents = (widget_value *) 0xDEADBEEF;
}
if (wv->next)
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x0000049d,
struct _widget_value * next = 0x008381f8
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x0083b660
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x00000468,
struct _widget_value * next = 0x00838020
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x00000453,
struct _widget_value * next = 0x0083c4a0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x0000043e,
struct _widget_value * next = 0x00839030
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x000003f1,
struct _widget_value * next = 0x0083c1b0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
0111046B emacs.exe:0111046B free_menubar_widget_value_tree w32menu.c:1084
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828210548,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00837fc0,
XtPointer call_data = 0x000003e5,
struct _widget_value * next = 0x00000000
}
)
...
{
free_menubar_widget_value_tree (wv->contents);
> wv->contents = (widget_value *) 0xDEADBEEF;
}
if (wv->next)
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828210452,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x000003dd,
struct _widget_value * next = 0x00838eb0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x0083dfa0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828210308,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x00000378,
struct _widget_value * next = 0x0083c0f0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x0000030b,
struct _widget_value * next = 0x00838350
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x00000269,
struct _widget_value * next = 0x0083bde0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x0083c680
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828116292,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x00000259,
struct _widget_value * next = 0x00838260
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828116084,
Boolean enabled = 0,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x00000251,
struct _widget_value * next = 0x0083bdb0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828102516,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x000001e4,
struct _widget_value * next = 0x0083c050
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 824014472,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x000001dc,
struct _widget_value * next = 0x0083b7e0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 824014552,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x000001d4,
struct _widget_value * next = 0x00838f10
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 824014640,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x000001cc,
struct _widget_value * next = 0x0083c1e0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 828101908,
Boolean enabled = 0,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x00000000,
XtPointer call_data = 0x000001c4,
struct _widget_value * next = 0x0083c180
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
0111046B emacs.exe:0111046B free_menubar_widget_value_tree w32menu.c:1084
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x0083c120,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x0083b8d0
}
)
...
{
free_menubar_widget_value_tree (wv->contents);
> wv->contents = (widget_value *) 0xDEADBEEF;
}
if (wv->next)
...
01110485 emacs.exe:01110485 free_menubar_widget_value_tree w32menu.c:1089
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0xdeadbeef,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x00837ed0
}
)
...
{
free_menubar_widget_value_tree (wv->next);
> wv->next = (widget_value *) 0xDEADBEEF;
}
BLOCK_INPUT;
...
0111046B emacs.exe:0111046B free_menubar_widget_value_tree w32menu.c:1084
void free_menubar_widget_value_tree(
widget_value * wv = &{
char * name = 0xdeadbeef,
char * value = 0xdeadbeef,
char * key = 0xdeadbeef,
int help = 290806788,
Boolean enabled = 1,
Boolean selected = 0,
enum button_type button_type = BUTTON_TYPE_NONE,
Boolean title = 0,
struct _widget_value * contents = 0x0083c470,
XtPointer call_data = 0x00000000,
struct _widget_value * next = 0x00000000
}
)
...
{
free_menubar_widget_value_tree (wv->contents);
> wv->contents = (widget_value *) 0xDEADBEEF;
}
if (wv->next)
...
01110E7B emacs.exe:01110E7B set_frame_menubar w32menu.c:1517
void set_frame_menubar(
FRAME_PTR f = &{
int size = 536871998,
struct Lisp_Vector * next = 0x01ce8300,
int name = 843753044,
int icon_name = 290806788,
int title = 290806788,
int focus_frame = 290806788,
int root_window = 1108712448,
int selected_window = 1108712448,
int minibuffer_window = 1104072192,
int param_alist = 1373797428,
int scroll_bars = 1113417728,
int condemned_scroll_bars = 290806788,
int menu_bar_items = 1104009216,
int face_alist = 1372527148,
int menu_bar_vector = 1104330752,
int menu_bar_items_used = 5893,
int buffer_predicate = 290806788,
int buffer_list = 1375180340,
int menu_bar_window = 1104156672,
int tool_bar_window = 1104163328,
int tool_bar_items = 290806788,
int desired_tool_bar_string = 290806788,
int current_tool_bar_string = 290806788,
struct face_cache * face_cache = 0x01cea520,
char * namebuf = 0x01575f68,
struct glyph_pool * current_pool = 0x00000000,
struct glyph_pool * desired_pool = 0x00000000,
struct glyph_matrix * desired_matrix = 0x00000000,
struct glyph_matrix * current_matrix = 0x00000000,
unsigned int glyphs_initialized_p,
int tool_bar_lines = 0,
int n_tool_bar_items = 0,
char * decode_mode_spec_buffer = 0x01d05e00,
int * insert_line_cost = 0x02088900,
int * delete_line_cost = 0x01e06300,
int * insert_n_lines_cost = 0x01e06200,
int * delete_n_lines_cost = 0x01ff0000,
int height = 35,
int width = 96,
int window_width = 100,
int window_height = 0,
int new_height = 0,
int new_width = 0,
enum output_method output_method = output_w32,
union output_data output_data = {
struct x_output * x = 0x01cddb00,
struct w32_output * w32 = 0x01cddb00,
struct mac_output * mac = 0x01cddb00,
int nothing = 30268160
},
int menu_bar_lines = 0,
int external_menu_bar = 1,
char display_preempted = 0,
char visible = 1,
char iconified = 0,
char async_visible = 1,
char async_iconified = 0,
char garbaged = 0,
char has_minibuffer = 1,
char wants_modeline = 1,
char can_have_scroll_bars = 1,
enum vertical_scroll_bar_type vertical_scroll_bar_type
= vertical_scroll_bar_right,
char auto_raise = 0,
char auto_lower = 0,
char no_split = 0,
char explicit_name = 0,
char window_sizes_changed = 0,
char * message_buf = 0x01d05000,
int scroll_bottom_vpos = -1,
int scroll_bar_pixel_width = 16,
int scroll_bar_cols = 2,
int cost_calculation_baud_rate = 19200,
char mouse_moved = 1,
double gamma = 0.000000,
int extra_line_spacing = 0,
unsigned int resized_p
},
int first_time = 0,
int deep_p = 1
)
...
{
> HMENU old_widget = f->output_data.w32->menubar_widget;
f->output_data.w32->menubar_widget = menubar_widget;
...
011101DF emacs.exe:011101DF x_activate_menubar w32menu.c:958
void x_activate_menubar(
FRAME_PTR f = &{
int size = 536871998,
struct Lisp_Vector * next = 0x01ce8300,
int name = 843753044,
int icon_name = 290806788,
int title = 290806788,
int focus_frame = 290806788,
int root_window = 1108712448,
int selected_window = 1108712448,
int minibuffer_window = 1104072192,
int param_alist = 1373797428,
int scroll_bars = 1113417728,
int condemned_scroll_bars = 290806788,
int menu_bar_items = 1104009216,
int face_alist = 1372527148,
int menu_bar_vector = 1104330752,
int menu_bar_items_used = 5893,
int buffer_predicate = 290806788,
int buffer_list = 1375180340,
int menu_bar_window = 1104156672,
int tool_bar_window = 1104163328,
int tool_bar_items = 290806788,
int desired_tool_bar_string = 290806788,
int current_tool_bar_string = 290806788,
struct face_cache * face_cache = 0x01cea520,
char * namebuf = 0x01575f68,
struct glyph_pool * current_pool = 0x00000000,
struct glyph_pool * desired_pool = 0x00000000,
struct glyph_matrix * desired_matrix = 0x00000000,
struct glyph_matrix * current_matrix = 0x00000000,
unsigned int glyphs_initialized_p,
int tool_bar_lines = 0,
int n_tool_bar_items = 0,
char * decode_mode_spec_buffer = 0x01d05e00,
int * insert_line_cost = 0x02088900,
int * delete_line_cost = 0x01e06300,
int * insert_n_lines_cost = 0x01e06200,
int * delete_n_lines_cost = 0x01ff0000,
int height = 35,
int width = 96,
int window_width = 100,
int window_height = 0,
int new_height = 0,
int new_width = 0,
enum output_method output_method = output_w32,
union output_data output_data = {
struct x_output * x = 0x01cddb00,
struct w32_output * w32 = 0x01cddb00,
struct mac_output * mac = 0x01cddb00,
int nothing = 30268160
},
int menu_bar_lines = 0,
int external_menu_bar = 1,
char display_preempted = 0,
char visible = 1,
char iconified = 0,
char async_visible = 1,
char async_iconified = 0,
char garbaged = 0,
char has_minibuffer = 1,
char wants_modeline = 1,
char can_have_scroll_bars = 1,
enum vertical_scroll_bar_type vertical_scroll_bar_type
= vertical_scroll_bar_right,
char auto_raise = 0,
char auto_lower = 0,
char no_split = 0,
char explicit_name = 0,
char window_sizes_changed = 0,
char * message_buf = 0x01d05000,
int scroll_bottom_vpos = -1,
int scroll_bar_pixel_width = 16,
int scroll_bar_cols = 2,
int cost_calculation_baud_rate = 19200,
char mouse_moved = 1,
double gamma = 0.000000,
int extra_line_spacing = 0,
unsigned int resized_p
}
)
...
/* Signal input thread to return from WM_INITMENU. */
> complete_deferred_msg (FRAME_W32_WINDOW (f), WM_INITMENU, 0);
}
...
01009761 emacs.exe:01009761 kbd_buffer_get_event keyboard.c:3783
static int kbd_buffer_get_event(
KBOARD * * kbp = &0x0125d220,
int * used_mouse_menu = &0
)
...
input_pending = readable_events (0);
if (FRAME_LIVE_P (XFRAME (event->frame_or_window)))
> x_activate_menubar (XFRAME (event->frame_or_window));
}
#endif
...
010081C3 emacs.exe:010081C3 read_char keyboard.c:2638
int read_char(
int commandflag = 1,
int nmaps = 11,
int * maps = &1373421628,
int prev_event = 290806788,
int * used_mouse_menu = &0
)
...
restore_getcjmp (local_getcjmp);
timer_start_idle ();
> c = kbd_buffer_get_event (&kb, used_mouse_menu);
restore_getcjmp (save_jump);
...
0100EAC9 emacs.exe:0100EAC9 read_key_sequence keyboard.c:8363
static int read_key_sequence(
int * keybuf = &299433876,
int bufsize = 30,
int prompt = 290806788,
int dont_downcase_last = 0,
int can_return_switch_frame = 1,
int fix_current_buffer = 1
)
...
}
#endif
> key = read_char (NILP (prompt), nmaps,
(Lisp_Object *) submaps, last_nonmenu_event,
&used_mouse_menu);
...
01006750 emacs.exe:01006750 command_loop_1 keyboard.c:1470
int command_loop_1(
)
...
/* Read next key sequence; i gets its length. */
> i = read_key_sequence (keybuf, sizeof keybuf / sizeof keybuf[0],
Qnil, 0, 1, 1);
...
0101AE4C emacs.exe:0101AE4C internal_condition_case eval.c:1349
int internal_condition_case(
int ()(void) * bfun = &0x01006454,
int handlers = 290929124,
int ()(void) * hfun = &0x01005f64
)
...
handlerlist = &h;
> val = (*bfun) ();
catchlist = c.next;
handlerlist = h.next;
...
01006210 emacs.exe:01006210 command_loop_2 keyboard.c:1271
int command_loop_2(
)
...
do
> val = internal_condition_case (command_loop_1, Qerror, cmd_error);
while (!NILP (val));
...
0101A9E4 emacs.exe:0101A9E4 internal_catch eval.c:1109
int internal_catch(
int tag = 290881452,
int ()(void) * func = &0x010061f0,
int arg = 290806788
)
...
/* Call FUNC. */
if (! _setjmp (c.jmp))
> c.val = (*func) (arg);
/* Throw works by a longjmp that comes right here. */
...
010061C2 emacs.exe:010061C2 command_loop keyboard.c:1251
int command_loop(
)
...
internal_catch (Qtop_level, top_level_1, Qnil);
internal_catch (Qtop_level, command_loop_2, Qnil);
> executing_macro = Qnil;
/* End of file in -batch run causes exit here. */
...
01005D33 emacs.exe:01005D33 recursive_edit_1 keyboard.c:966
int recursive_edit_1(
)
...
redisplaying_p = 0;
> val = command_loop ();
if (EQ (val, Qt))
Fsignal (Qquit, Qnil);
...
01005E5F emacs.exe:01005E5F Frecursive_edit keyboard.c:1023
int Frecursive_edit(
)
...
recursive_edit_1 ();
> return unbind_to (count, Qnil);
}
...
01003298 emacs.exe:01003298 main emacs.c:1627
int main(
int argc = 1,
char * * argv = &0x012584c0,
char * * envp = &0x43414d45
)
...
Frecursive_edit ();
/* NOTREACHED */
> return 0;
}
...
010010EC emacs.exe:010010EC
01001203 emacs.exe:01001203
010042CD emacs.exe:010042CD _start unexw32.c:135
void _start(
)
...
nCmdShow = SW_SHOWDEFAULT;
#endif
> mainCRTStartup ();
}
...
77F1BBB5 KERNEL32.dll:77F1BBB5 GetProcessPriorityBoost
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-24 18:55 David Ponce
@ 2002-07-25 18:07 ` Richard Stallman
2002-07-26 12:30 ` David Ponce
0 siblings, 1 reply; 13+ messages in thread
From: Richard Stallman @ 2002-07-25 18:07 UTC (permalink / raw)
Cc: emacs-devel
The widget_value structures are not Lisp data; they are explicitly
allocated and freed. So I don't think GC is responsible for this.
It appears to me that ASCII text got written throughout the
last real widget_value structure encountered:
int help = 875524,
Boolean enabled = 'H',
Boolean selected = 'i',
enum button_type button_type = 1751607660,
Boolean title = 't',
struct _widget_value * contents = 0x6374616d,
XtPointer call_data = 0x20646568,
struct _widget_value * next = 0x746e7953
This appears to say "Hilight" and "matched Synt".
(I suspect there are three other characters in between them
that did not show up in this output.)
The value of `help' is peculiar since it does not translate
into ASCII text, and yet it does not seem like a valid value
to be there (it would normally be a Lisp string object).
One interesting question is what data is in core before the start of
this object. Is any ASCII text present there?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-25 18:07 ` Richard Stallman
@ 2002-07-26 12:30 ` David Ponce
2002-07-27 18:52 ` Richard Stallman
0 siblings, 1 reply; 13+ messages in thread
From: David Ponce @ 2002-07-26 12:30 UTC (permalink / raw)
Cc: emacs-devel
>
>
>One interesting question is what data is in core before the start of
>this object. Is any ASCII text present there?
>
Hi,
I worked a little more on this problem and, simply calling fprintf in
various locations in w32menu.c (I don't have a debugger), I found that
the function `single_submenu' seems to receive corrupted data in
static variable `menu_items'.
Notice that I only observed garbaged menu item names in dynamic menus
like "Buffers" (I use msb) or imenu.
More details...
Only after this line (w32menu.c::1268):
wv->name = (char *) SDATA (item_name);
The following fprintf showed corrupted data:
fprintf(stderr,
"single_submenu::1268/wv->name = SDATA (item_name) = %p@%s\n",
wv->name, wv->name);
Here is a snippet of the printed data (the first value of `item_name'
seems correct, but the next ones are corrupted):
[...]
single_submenu::1268/wv->name = SDATA (item_name) = 01772128@Select and
Paste
single_submenu::1268/wv->name = SDATA (item_name) = 01EFC1D0@
wv->name...DEADBEEF;
single_submenu::1268/wv->name = SDATA (item_name) = 01EFC1B4@
wv->nam...DEADBEEF;
single_submenu::1268/wv->name = SDATA (item_name) = 01EF2B70@: Ditto.
single_submenu::1268/wv->name = SDATA (item_name) = 01EF2B80@: Moved
definitions.
single_submenu::1268/wv->name = SDATA (item_name) = 01EFC198@K Void
va...vironment.
single_submenu::1268/wv->name = SDATA (item_name) = 01EFC17C@;; Unused
...$nterm))
[...]
`item_name' is a local Lisp_Object variable initialized to
(w32menu.c::1240):
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
`menu_items' is initialized in the function `set_frame_menubar'
(w32menu.c::1395):
menu_items = f->menu_bar_vector;
It seems that f->menu_bar_vector is setup in keyboard.c in function
`menu_bar_items'. Maybe is there a problem here?
I had a look at this function, but I lack more knowledge of Emacs
internal (and probably C) to really understand its code.
Nevertheless, I hope this report will help.
David
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-26 12:30 ` David Ponce
@ 2002-07-27 18:52 ` Richard Stallman
2002-07-28 16:56 ` David Ponce
0 siblings, 1 reply; 13+ messages in thread
From: Richard Stallman @ 2002-07-27 18:52 UTC (permalink / raw)
Cc: emacs-devel
I worked a little more on this problem and, simply calling fprintf in
various locations in w32menu.c (I don't have a debugger), I found that
the function `single_submenu' seems to receive corrupted data in
static variable `menu_items'.
You have made significant progress, but we don't know the answer yet.
Can you determine where that data becomes corrupted?
Is it written wrong at the start, or does it get
clobbered later on?
`item_name' is a local Lisp_Object variable initialized to
(w32menu.c::1240):
Can you determine what value item_name has at that point?
Is it a Lisp string? If so, what is its text?
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
What is the value of i when the invalid data comes out?
What array index?
It seems that f->menu_bar_vector is setup in keyboard.c in function
`menu_bar_items'. Maybe is there a problem here?
It could be. Could you examine the contents of this vector
right after that function is finished? In particular,
what is the value found at the array index that the bad data later
comes from?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-27 18:52 ` Richard Stallman
@ 2002-07-28 16:56 ` David Ponce
2002-07-29 17:30 ` Richard Stallman
0 siblings, 1 reply; 13+ messages in thread
From: David Ponce @ 2002-07-28 16:56 UTC (permalink / raw)
Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 2537 bytes --]
Hi Richard,
>You have made significant progress, but we don't know the answer yet.
>
>Can you determine where that data becomes corrupted?
>Is it written wrong at the start, or does it get
>clobbered later on?
>
Thank you for your support!
I worked hard to find the bug that corrupted menu strings, and I
think I finally found it!
In fact, after displaying memory locations of menu item strings in
`widget_value' data structures, I noticed that sometimes their
contents changed (not the location) between their initialization in
`single_submenu' and their use in `add_menu_item'.
This looked like a bad interaction with GC. I carefully reviewed the
code and was first disappointed because all the Lisp strings that
produced menu item strings seemed correctly protected from GC! I
looked more thoroughly at the GC code, and discovered that the data
part of Lisp strings may be relocated when GC compacts the Lisp string
storage. Even when the base string Lisp_Object is protected!
So, I hacked w32menu.c to used safe local copy of menu item strings,
and the bug disappeared :-)
From that base, I took time to properly update w32menu.c, and fixed
another bug too, related to pop up menu cleanup. Finally I cleaned
up the code to generalize use of AREF, ASET and ASIZE macros.
Attached you will find the patch, the change log is at end.
With the patch menus work very well now, with no noticeable slow down
(I used the faster Win32 API to alloc/free memory).
I don't know if it is possible, or if that could solve such problems
(is it guaranteed that GC can't raise when a menu is showing up?),
but perhaps a more general solution, probably with more impact, would
be to directly use Lisp strings in `widget_value', like for help
items?
What do you think?
Sincerely,
David
------------------------ Change Log --------------------------------
(local_heap, local_alloc, local_free): New macros.
(malloc_widget_value, free_widget_value)
(free_menubar_widget_value_tree)
(w32_free_submenu_strings): Use them.
(local-string): New function.
(single_submenu, set_frame_menubar)
(w32_menu_show, add_menu_item): Use it.
(push_submenu_start, push_submenu_end, push_left_right_boundary)
(push_menu_pane, push_menu_item, single_keymap_panes)
(single_menu_item, Fx_popup_menu, menubar_selection_callback)
(single_submenu, set_frame_menubar)
(w32_menu_show, w32_dialog_show): Use AREF, ASET, ASIZE.
(Fx_popup_menu): Don't show pop up menu until preceding one is
actually cleaned up. Moved UNGCPRO outside #ifdef HAVE_MENUS block.
[-- Attachment #2: w32menu.patch --]
[-- Type: text/x-patch, Size: 31233 bytes --]
*** w32menu.c.ori Mon Jul 15 10:48:32 2002
--- w32menu.c Sun Jul 28 18:35:13 2002
***************
*** 112,120 ****
#endif
} widget_value;
! /* LocalAlloc/Free is a reasonably good allocator. */
! #define malloc_widget_value() (void*)LocalAlloc (LMEM_ZEROINIT, sizeof (widget_value))
! #define free_widget_value(wv) LocalFree (wv)
/******************************************************************/
--- 112,124 ----
#endif
} widget_value;
! /* Local memory management */
! #define local_heap (GetProcessHeap ())
! #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
! #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
!
! #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
! #define free_widget_value(wv) (local_free ((wv)))
/******************************************************************/
***************
*** 318,324 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
menu_items_submenu_depth++;
}
--- 322,328 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qnil);
menu_items_submenu_depth++;
}
***************
*** 330,336 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
menu_items_submenu_depth--;
}
--- 334,340 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qlambda);
menu_items_submenu_depth--;
}
***************
*** 342,348 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
}
/* Start a new menu pane in menu_items.
--- 346,352 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qquote);
}
/* Start a new menu pane in menu_items.
***************
*** 357,365 ****
if (menu_items_submenu_depth == 0)
menu_items_n_panes++;
! XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
! XVECTOR (menu_items)->contents[menu_items_used++] = name;
! XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
}
/* Push one menu item into the current pane. NAME is the string to
--- 361,369 ----
if (menu_items_submenu_depth == 0)
menu_items_n_panes++;
! ASET (menu_items, menu_items_used++, Qt);
! ASET (menu_items, menu_items_used++, name);
! ASET (menu_items, menu_items_used++, prefix_vec);
}
/* Push one menu item into the current pane. NAME is the string to
***************
*** 377,390 ****
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = name;
! XVECTOR (menu_items)->contents[menu_items_used++] = enable;
! XVECTOR (menu_items)->contents[menu_items_used++] = key;
! XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
! XVECTOR (menu_items)->contents[menu_items_used++] = def;
! XVECTOR (menu_items)->contents[menu_items_used++] = type;
! XVECTOR (menu_items)->contents[menu_items_used++] = selected;
! XVECTOR (menu_items)->contents[menu_items_used++] = help;
}
\f
/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
--- 381,394 ----
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, name);
! ASET (menu_items, menu_items_used++, enable);
! ASET (menu_items, menu_items_used++, key);
! ASET (menu_items, menu_items_used++, equiv);
! ASET (menu_items, menu_items_used++, def);
! ASET (menu_items, menu_items_used++, type);
! ASET (menu_items, menu_items_used++, selected);
! ASET (menu_items, menu_items_used++, help);
}
\f
/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
***************
*** 450,462 ****
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
! int len = XVECTOR (item)->size;
int c;
for (c = 0; c < len; c++)
{
Lisp_Object character;
XSETFASTINT (character, c);
! single_menu_item (character, XVECTOR (item)->contents[c],
&pending_maps, notreal, maxdepth);
}
}
--- 454,466 ----
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
! int len = ASIZE (item);
int c;
for (c = 0; c < len; c++)
{
Lisp_Object character;
XSETFASTINT (character, c);
! single_menu_item (character, AREF (item, c),
&pending_maps, notreal, maxdepth);
}
}
***************
*** 504,510 ****
if (!res)
return; /* Not a menu item. */
! map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
if (notreal)
{
--- 508,514 ----
if (!res)
return; /* Not a menu item. */
! map = AREF (item_properties, ITEM_PROPERTY_MAP);
if (notreal)
{
***************
*** 515,522 ****
return;
}
! enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
! item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
if (!NILP (map) && SREF (item_string, 0) == '@')
{
--- 519,526 ----
return;
}
! enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
! item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
if (!NILP (map) && SREF (item_string, 0) == '@')
{
***************
*** 528,538 ****
}
push_menu_item (item_string, enabled, key,
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
/* Display a submenu using the toolkit. */
if (! (NILP (map) || NILP (enabled)))
--- 532,542 ----
}
push_menu_item (item_string, enabled, key,
! AREF (item_properties, ITEM_PROPERTY_DEF),
! AREF (item_properties, ITEM_PROPERTY_KEYEQ),
! AREF (item_properties, ITEM_PROPERTY_TYPE),
! AREF (item_properties, ITEM_PROPERTY_SELECTED),
! AREF (item_properties, ITEM_PROPERTY_HELP));
/* Display a submenu using the toolkit. */
if (! (NILP (map) || NILP (enabled)))
***************
*** 745,751 ****
/* Make that be the pane title of the first pane. */
if (!NILP (prompt) && menu_items_n_panes >= 0)
! XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
keymaps = 1;
}
--- 749,755 ----
/* Make that be the pane title of the first pane. */
if (!NILP (prompt) && menu_items_n_panes >= 0)
! ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt);
keymaps = 1;
}
***************
*** 777,783 ****
/* Make the title be the pane title of the first pane. */
if (!NILP (title) && menu_items_n_panes >= 0)
! XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
keymaps = 1;
}
--- 781,787 ----
/* Make the title be the pane title of the first pane. */
if (!NILP (title) && menu_items_n_panes >= 0)
! ASET (menu_items, MENU_ITEMS_PANE_NAME, title);
keymaps = 1;
}
***************
*** 800,805 ****
--- 804,819 ----
}
#ifdef HAVE_MENUS
+ /* If resources from a previous popup menu exist yet, does nothing
+ until the `menu_free_timer' has freed them (see w32fns.c).
+ */
+ if (current_popup_menu)
+ {
+ discard_menu_items ();
+ UNGCPRO;
+ return Qnil;
+ }
+
/* Display them in a menu. */
BLOCK_INPUT;
***************
*** 808,816 ****
UNBLOCK_INPUT;
discard_menu_items ();
UNGCPRO;
- #endif /* HAVE_MENUS */
if (error_name) error (error_name);
return selection;
--- 822,830 ----
UNBLOCK_INPUT;
discard_menu_items ();
+ #endif /* HAVE_MENUS */
UNGCPRO;
if (error_name) error (error_name);
return selection;
***************
*** 981,1005 ****
i = 0;
while (i < f->menu_bar_items_used)
{
! if (EQ (XVECTOR (vector)->contents[i], Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (vector)->contents[i], Qt))
{
! prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
if ((int) (EMACS_INT) client_data == i)
--- 995,1019 ----
i = 0;
while (i < f->menu_bar_items_used)
{
! if (EQ (AREF (vector, i), Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (AREF (vector, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (vector, i), Qt))
{
! prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
if ((int) (EMACS_INT) client_data == i)
***************
*** 1051,1056 ****
--- 1065,1089 ----
f->output_data.w32->menubar_active = 0;
}
+ /* Return a local copy of the given input string STR.
+ Does nothing if STR is 0.
+
+ It is necessary to use safe local copy of string data stored in
+ widget_value because the data part of Lisp strings can be relocated
+ when the GC compacts string storage. Even when the base string
+ Lisp_Object is protected! */
+ char *
+ local_string (const char *str)
+ {
+ if (str)
+ {
+ char *clone = (char *) local_alloc (strlen (str) + 1);
+ strcpy (clone, str);
+ return clone;
+ }
+ return 0;
+ }
+
/* Allocate a widget_value, blocking input. */
widget_value *
***************
*** 1075,1081 ****
widget_value *wv;
{
if (! wv) return;
!
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
if (wv->contents && (wv->contents != (widget_value*)1))
--- 1108,1118 ----
widget_value *wv;
{
if (! wv) return;
!
! local_free (wv->name);
! local_free (wv->value);
! local_free (wv->key);
!
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
if (wv->contents && (wv->contents != (widget_value*)1))
***************
*** 1148,1154 ****
submenu_stack
= (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
wv = xmalloc_widget_value ();
! wv->name = "menu";
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
--- 1185,1191 ----
submenu_stack
= (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
wv = xmalloc_widget_value ();
! wv->name = local_string ("menu");
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1164,1203 ****
i = previous_items;
while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
! prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
}
#endif
pane_string = (NILP (pane_name)
--- 1201,1240 ----
i = previous_items;
while (i < menu_items_used)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (menu_items, i), Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
! else if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
#endif
pane_string = (NILP (pane_name)
***************
*** 1222,1227 ****
--- 1259,1265 ----
This is a kludge, but this isn't worth more time. */
if (!NILP (prefix) && wv->name[0] == '@')
wv->name++;
+ wv->name = local_string (wv->name);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1249,1261 ****
if (STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
--- 1287,1299 ----
if (STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
#endif /* not HAVE_MULTILINGUAL_MENU */
***************
*** 1265,1273 ****
else
save_wv->contents = wv;
! wv->name = (char *) SDATA (item_name);
if (!NILP (descrip))
! wv->key = (char *) SDATA (descrip);
wv->value = 0;
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
--- 1303,1311 ----
else
save_wv->contents = wv;
! wv->name = local_string ((char *) SDATA (item_name));
if (!NILP (descrip))
! wv->key = local_string ((char *) SDATA (descrip));
wv->value = 0;
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
***************
*** 1334,1340 ****
deep_p = 1;
wv = xmalloc_widget_value ();
! wv->name = "menubar";
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
--- 1372,1378 ----
deep_p = 1;
wv = xmalloc_widget_value ();
! wv->name = local_string ("menubar");
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1395,1407 ****
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
init_menu_items ();
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object key, string, maps;
! key = XVECTOR (items)->contents[i];
! string = XVECTOR (items)->contents[i + 1];
! maps = XVECTOR (items)->contents[i + 2];
if (NILP (string))
break;
--- 1433,1445 ----
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
init_menu_items ();
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object key, string, maps;
! key = AREF (items, i);
! string = AREF (items, i + 1);
! maps = AREF (items, i + 2);
if (NILP (string))
break;
***************
*** 1426,1432 ****
for (i = 0; i < previous_menu_items_used; i++)
if (menu_items_used == i
! || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
break;
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
--- 1464,1470 ----
for (i = 0; i < previous_menu_items_used; i++)
if (menu_items_used == i
! || (!EQ (previous_items[i], AREF (menu_items, i))))
break;
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
***************
*** 1442,1454 ****
Windows takes care of this for normal string items, but
not for owner-drawn items or additional item-info. */
wv = first_wv->contents;
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object string;
! string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
! wv->name = (char *) SDATA (string);
wv = wv->next;
}
--- 1480,1492 ----
Windows takes care of this for normal string items, but
not for owner-drawn items or additional item-info. */
wv = first_wv->contents;
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object string;
! string = AREF (items, i + 1);
if (NILP (string))
break;
! wv->name = local_string ((char *) SDATA (string));
wv = wv->next;
}
***************
*** 1462,1477 ****
just the top level menu bar strings. */
items = FRAME_MENU_BAR_ITEMS (f);
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object string;
! string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
wv = xmalloc_widget_value ();
! wv->name = (char *) SDATA (string);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
--- 1500,1515 ----
just the top level menu bar strings. */
items = FRAME_MENU_BAR_ITEMS (f);
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object string;
! string = AREF (items, i + 1);
if (NILP (string))
break;
wv = xmalloc_widget_value ();
! wv->name = local_string ((char *) SDATA (string));
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1613,1619 ****
/* Create a tree of widget_value objects
representing the panes and their items. */
wv = xmalloc_widget_value ();
! wv->name = "menu";
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
--- 1651,1657 ----
/* Create a tree of widget_value objects
representing the panes and their items. */
wv = xmalloc_widget_value ();
! wv->name = local_string ("menu");
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1625,1631 ****
i = 0;
while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
--- 1663,1669 ----
i = 0;
while (i < menu_items_used)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
***************
*** 1633,1653 ****
first_pane = 1;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
first_pane = 0;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
--- 1671,1691 ----
first_pane = 1;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
first_pane = 0;
i++;
}
! else if (EQ (AREF (menu_items, i), Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
! else if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
***************
*** 1658,1664 ****
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
}
#endif
pane_string = (NILP (pane_name)
--- 1696,1702 ----
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
#endif
pane_string = (NILP (pane_name)
***************
*** 1681,1686 ****
--- 1719,1725 ----
wv->name = pane_string;
if (keymaps && !NILP (prefix))
wv->name++;
+ wv->name = local_string (wv->name);
wv->value = 0;
wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
***************
*** 1713,1724 ****
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
--- 1752,1763 ----
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
#endif /* not HAVE_MULTILINGUAL_MENU */
***************
*** 1727,1735 ****
prev_wv->next = wv;
else
save_wv->contents = wv;
! wv->name = (char *) SDATA (item_name);
if (!NILP (descrip))
! wv->key = (char *) SDATA (descrip);
wv->value = 0;
/* Use the contents index as call_data, since we are
restricted to 16-bits. */
--- 1766,1774 ----
prev_wv->next = wv;
else
save_wv->contents = wv;
! wv->name = local_string ((char *) SDATA (item_name));
if (!NILP (descrip))
! wv->key = local_string ((char *) SDATA (descrip));
wv->value = 0;
/* Use the contents index as call_data, since we are
restricted to 16-bits. */
***************
*** 1765,1771 ****
/* Maybe replace this separator with a bitmap or owner-draw item
so that it looks better. Having two separators looks odd. */
! wv_sep->name = "--";
wv_sep->next = first_wv->contents;
wv_sep->help = Qnil;
--- 1804,1810 ----
/* Maybe replace this separator with a bitmap or owner-draw item
so that it looks better. Having two separators looks odd. */
! wv_sep->name = local_string ("--");
wv_sep->next = first_wv->contents;
wv_sep->help = Qnil;
***************
*** 1773,1779 ****
if (STRING_MULTIBYTE (title))
title = ENCODE_SYSTEM (title);
#endif
! wv_title->name = (char *) SDATA (title);
wv_title->enabled = TRUE;
wv_title->title = TRUE;
wv_title->button_type = BUTTON_TYPE_NONE;
--- 1812,1818 ----
if (STRING_MULTIBYTE (title))
title = ENCODE_SYSTEM (title);
#endif
! wv_title->name = local_string ((char *) SDATA (title));
wv_title->enabled = TRUE;
wv_title->title = TRUE;
wv_title->button_type = BUTTON_TYPE_NONE;
***************
*** 1818,1848 ****
i = 0;
while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
! prefix
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
else
{
! entry
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
if (menu_item_selection == i)
{
if (keymaps != 0)
--- 1857,1885 ----
i = 0;
while (i < menu_items_used)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (menu_items, i), Qt))
{
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else
{
! entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == i)
{
if (keymaps != 0)
***************
*** 1903,1910 ****
{
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
! prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
--- 1940,1947 ----
{
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
! prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
***************
*** 1924,1934 ****
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, help;
! item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
! enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
! descrip
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
! help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
if (NILP (item_name))
{
--- 1961,1970 ----
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, help;
! item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
! enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
! descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
! help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
if (NILP (item_name))
{
***************
*** 1957,1963 ****
if (!NILP (descrip))
wv->key = (char *) SDATA (descrip);
wv->value = (char *) SDATA (item_name);
! wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
wv->enabled = !NILP (enable);
wv->help = Qnil;
prev_wv = wv;
--- 1993,1999 ----
if (!NILP (descrip))
wv->key = (char *) SDATA (descrip);
wv->value = (char *) SDATA (item_name);
! wv->call_data = (void *) &AREF (menu_items, i);
wv->enabled = !NILP (enable);
wv->help = Qnil;
prev_wv = wv;
***************
*** 2027,2042 ****
{
Lisp_Object entry;
! if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
! prefix
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
if (menu_item_selection == i)
{
if (keymaps != 0)
--- 2063,2076 ----
{
Lisp_Object entry;
! if (EQ (AREF (menu_items, i), Qt))
{
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == i)
{
if (keymaps != 0)
***************
*** 2117,2127 ****
we can't deallocate the memory otherwise. */
if (get_menu_item_info)
{
! out_string = (char *) LocalAlloc (LPTR, strlen (wv->name) + 1);
#ifdef MENU_DEBUG
! DebPrint ("Menu: allocing %ld for owner-draw", info.dwItemData);
#endif
- strcpy (out_string, wv->name);
fuFlags = MF_OWNERDRAW | MF_DISABLED;
}
else
--- 2151,2160 ----
we can't deallocate the memory otherwise. */
if (get_menu_item_info)
{
! out_string = local_string (wv->name);
#ifdef MENU_DEBUG
! DebPrint ("Menu: allocing %ld for owner-draw", out_string);
#endif
fuFlags = MF_OWNERDRAW | MF_DISABLED;
}
else
***************
*** 2277,2283 ****
#ifdef MENU_DEBUG
DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
#endif
! LocalFree (info.dwItemData);
}
/* Recurse down submenus. */
--- 2310,2316 ----
#ifdef MENU_DEBUG
DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
#endif
! local_free (info.dwItemData);
}
/* Recurse down submenus. */
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-28 16:56 ` David Ponce
@ 2002-07-29 17:30 ` Richard Stallman
2002-07-29 18:16 ` David Ponce
0 siblings, 1 reply; 13+ messages in thread
From: Richard Stallman @ 2002-07-29 17:30 UTC (permalink / raw)
Cc: emacs-devel
Is this comment in w32menu.c inaccurate?
/* Now GC cannot happen during the lifetime of the widget_value,
so it's safe to store data from a Lisp_String, as long as
local copies are made when the actual menu is created.
Windows takes care of this for normal string items, but
not for owner-drawn items or additional item-info. */
If it is inaccurate, why is that? How is it that GC happens in
between creation of the widget value and its use in add_menu_item?
Note that GC ought to be inhibited within set_frame_menubar
from this line
inhibit_garbage_collection ();
to this line
unbind_to (specpdl_count, Qnil);
Does the GC happen inside that range, or after?
Either way, it's a bug; the question is what bug.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-29 17:30 ` Richard Stallman
@ 2002-07-29 18:16 ` David Ponce
2002-07-30 18:46 ` Richard Stallman
0 siblings, 1 reply; 13+ messages in thread
From: David Ponce @ 2002-07-29 18:16 UTC (permalink / raw)
Cc: emacs-devel
>
>
>Is this comment in w32menu.c inaccurate?
>
> /* Now GC cannot happen during the lifetime of the widget_value,
> so it's safe to store data from a Lisp_String, as long as
> local copies are made when the actual menu is created.
> Windows takes care of this for normal string items, but
> not for owner-drawn items or additional item-info. */
>
Yes I think it is inaccurate.
IMO, GC cannot happen after the build of the widget_value tree is completed.
>If it is inaccurate, why is that? How is it that GC happens in
>between creation of the widget value and its use in add_menu_item?
>Note that GC ought to be inhibited within set_frame_menubar
>from this line
>
> inhibit_garbage_collection ();
>
>to this line
>
> unbind_to (specpdl_count, Qnil);
>
>Does the GC happen inside that range, or after?
>Either way, it's a bug; the question is what bug.
>
Yes GC seems to happen inside that range when building the widget_value
tree.
When it happens it can change the address of strings (when compacting
the string pool)
that are stored in already allocated widget_values.
I suppose it explains this comment
"/* Don't set wv->name here; GC during the loop might relocate it. */"
which appears inside that range.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
@ 2002-07-30 11:28 David PONCE
0 siblings, 0 replies; 13+ messages in thread
From: David PONCE @ 2002-07-30 11:28 UTC (permalink / raw)
Cc: emacs-devel
Richard,
I can confirm that GC is the cause of the problem. I printed
messages before, after, and in the middle of the loop that build the
widget_value tree and when entering GC. Here is a snippet of printed
result that clearly shows that GC happened while running
single_submenu:
[...]
w32menu.set_frame_menubar before init_menu_items consing/threshold(375580/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(375580/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(376568/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(376568/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(466128/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(466128/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(485808/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(485808/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(485920/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(485920/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(486276/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(486276/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(501404/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(501404/134217727)
*** GC entered consing/threshold(509952/10000000)
*** GC entered consing/threshold(872/10000000)
w32menu.set_frame_menubar after single_submenu consing/threshold(6444/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(6444/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(7120/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(7120/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(10568/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(10568/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(24800/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(24800/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(39056/134217727)
w32menu.set_frame_menubar before single_submenu consing/threshold(39056/134217727)
w32menu.set_frame_menubar after single_submenu consing/threshold(100504/134217727)
w32menu.set_frame_menubar after finish_menu_items consing/threshold(100504/134217727)
*** GC entered consing/threshold(101352/10000000)
[...]
In fact 10000000 is the `gc-cons-threshold' value that the Semantic
parser locally uses to speed up things. The parser is called from
`menu-bar-update-hook' to produce the parse tree used to build the
imenu index. And can be called too via an idle timer to re-parse the
buffer when necessary. Also the parser explicitly calls
`garbage-collect' to free memory before it locally binds
`gc-cons-threshold'. Maybe the parser hook or timer are
asynchronously activated while building the widget_value tree?
IMO it is definitively a bug in Emacs to consider that the range of
code that builds the menu tree is GC safe, because user's Lisp code
can call `garbage-collect' or re-bind `gc-cons-threshold' to a value
lower than the maximum one set by `inhibit_garbage_collection' to
inhibit GC. As Lisp strings data can be relocated even if the
Lisp_Object is protected, it is only safe to store string data
locations when it is really sure that GC can't happen.
My proposed patch to w32menu.c make widget_value insensible to GC
because it only contains pointers to safe strings, copied in local
heap. The counterpart is a little overhead. From what I observed, I
didn't noticed a significant slow down when using menus.
Maybe another possible solution could be that
`inhibit_garbage_collection' uses a flag to block GC? By default it
would be t to allow GC and could be set to nil to really disable GC.
Something like this:
(let ((inhibit_garbage_collection nil))
(garbage_collect) ;; Does nothing!
)
I don't know if a such flag should be exported to Lisp. Perhaps its
use would be dangerous!
David
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-29 18:16 ` David Ponce
@ 2002-07-30 18:46 ` Richard Stallman
0 siblings, 0 replies; 13+ messages in thread
From: Richard Stallman @ 2002-07-30 18:46 UTC (permalink / raw)
Cc: emacs-devel
>Does the GC happen inside that range, or after?
>Either way, it's a bug; the question is what bug.
>
Yes GC seems to happen inside that range when building the widget_value
tree.
Please show precisely how GC happens inside there. Then we can fix it.
A backtrace from GC within that area may be enough info.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
[not found] <3D2A791A00A0862A@mel-rta9.wanadoo.fr>
@ 2002-07-31 21:57 ` Richard Stallman
2002-07-31 22:37 ` David Ponce
0 siblings, 1 reply; 13+ messages in thread
From: Richard Stallman @ 2002-07-31 21:57 UTC (permalink / raw)
Cc: emacs-devel
I figured out how Lisp code was getting called during that loop.
xmenu.c had the same bug, so I fixed it there.
Now we need a Windows hacker to adapt the same fix to w32menu.c.
Perhaps macmenu.c needs the same change.
Thanks for figuring this out.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
2002-07-31 21:57 ` NT Emacs crashes when selecting a menubar item Richard Stallman
@ 2002-07-31 22:37 ` David Ponce
0 siblings, 0 replies; 13+ messages in thread
From: David Ponce @ 2002-07-31 22:37 UTC (permalink / raw)
Cc: emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1560 bytes --]
Richard Stallman wrote:
>I figured out how Lisp code was getting called during that loop.
>xmenu.c had the same bug, so I fixed it there.
>
>Now we need a Windows hacker to adapt the same fix to w32menu.c.
>Perhaps macmenu.c needs the same change.
>
>Thanks for figuring this out.
>
>
Hi Richard,
I adapted your changes from xmenu.c to the version of w32menu.c where
I fixed another bug with popup menu, and generalized use of the macros
AREF, ASET, ASIZE, to access vectors. Attached you will find a new
diff. The change log is at end.
I currently use this new version and can confirm that you fixed the bug
:-)
Thank you very much for your support!
David
------------ Change Log:
(local_heap, local_alloc, local_free): New macros.
(malloc_widget_value, free_widget_value)
(w32_free_submenu_strings): Use them.
(push_submenu_start, push_submenu_end, push_left_right_boundary)
(push_menu_pane, push_menu_item, single_keymap_panes)
(single_menu_item, Fx_popup_menu, menubar_selection_callback)
(single_submenu, set_frame_menubar)
(w32_menu_show, w32_dialog_show): Use AREF, ASET, ASIZE.
(Fx_popup_menu): Don't show pop up menu until preceding one is
actually cleaned up. Moved UNGCPRO outside #ifdef HAVE_MENUS block.
Changes adapted from xmenu.c
(set_frame_menubar): First parse all submenus,
then make widget_value trees from them.
Don't allocate any widget_value objects
until we are done with the parsing.
(parse_single_submenu): New function.
(digest_single_submenu): New function.
(single_submenu): Function deleted, replaced by those two.
[-- Attachment #2: w32menu.patch --]
[-- Type: text/x-patch, Size: 31663 bytes --]
*** w32menu.c.ori Mon Jul 15 10:48:32 2002
--- w32menu.c Wed Jul 31 21:22:29 2002
***************
*** 112,120 ****
#endif
} widget_value;
! /* LocalAlloc/Free is a reasonably good allocator. */
! #define malloc_widget_value() (void*)LocalAlloc (LMEM_ZEROINIT, sizeof (widget_value))
! #define free_widget_value(wv) LocalFree (wv)
/******************************************************************/
--- 112,124 ----
#endif
} widget_value;
! /* Local memory management */
! #define local_heap (GetProcessHeap ())
! #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
! #define local_free(p) (HeapFree (local_heap, 0, ((LPVOID) (p))))
!
! #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
! #define free_widget_value(wv) (local_free ((wv)))
/******************************************************************/
***************
*** 318,324 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
menu_items_submenu_depth++;
}
--- 322,328 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qnil);
menu_items_submenu_depth++;
}
***************
*** 330,336 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
menu_items_submenu_depth--;
}
--- 334,340 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qlambda);
menu_items_submenu_depth--;
}
***************
*** 342,348 ****
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
}
/* Start a new menu pane in menu_items.
--- 346,352 ----
if (menu_items_used + 1 > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, Qquote);
}
/* Start a new menu pane in menu_items.
***************
*** 357,365 ****
if (menu_items_submenu_depth == 0)
menu_items_n_panes++;
! XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
! XVECTOR (menu_items)->contents[menu_items_used++] = name;
! XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
}
/* Push one menu item into the current pane. NAME is the string to
--- 361,369 ----
if (menu_items_submenu_depth == 0)
menu_items_n_panes++;
! ASET (menu_items, menu_items_used++, Qt);
! ASET (menu_items, menu_items_used++, name);
! ASET (menu_items, menu_items_used++, prefix_vec);
}
/* Push one menu item into the current pane. NAME is the string to
***************
*** 377,390 ****
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
! XVECTOR (menu_items)->contents[menu_items_used++] = name;
! XVECTOR (menu_items)->contents[menu_items_used++] = enable;
! XVECTOR (menu_items)->contents[menu_items_used++] = key;
! XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
! XVECTOR (menu_items)->contents[menu_items_used++] = def;
! XVECTOR (menu_items)->contents[menu_items_used++] = type;
! XVECTOR (menu_items)->contents[menu_items_used++] = selected;
! XVECTOR (menu_items)->contents[menu_items_used++] = help;
}
\f
/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
--- 381,394 ----
if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
grow_menu_items ();
! ASET (menu_items, menu_items_used++, name);
! ASET (menu_items, menu_items_used++, enable);
! ASET (menu_items, menu_items_used++, key);
! ASET (menu_items, menu_items_used++, equiv);
! ASET (menu_items, menu_items_used++, def);
! ASET (menu_items, menu_items_used++, type);
! ASET (menu_items, menu_items_used++, selected);
! ASET (menu_items, menu_items_used++, help);
}
\f
/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
***************
*** 450,462 ****
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
! int len = XVECTOR (item)->size;
int c;
for (c = 0; c < len; c++)
{
Lisp_Object character;
XSETFASTINT (character, c);
! single_menu_item (character, XVECTOR (item)->contents[c],
&pending_maps, notreal, maxdepth);
}
}
--- 454,466 ----
else if (VECTORP (item))
{
/* Loop over the char values represented in the vector. */
! int len = ASIZE (item);
int c;
for (c = 0; c < len; c++)
{
Lisp_Object character;
XSETFASTINT (character, c);
! single_menu_item (character, AREF (item, c),
&pending_maps, notreal, maxdepth);
}
}
***************
*** 504,510 ****
if (!res)
return; /* Not a menu item. */
! map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
if (notreal)
{
--- 508,514 ----
if (!res)
return; /* Not a menu item. */
! map = AREF (item_properties, ITEM_PROPERTY_MAP);
if (notreal)
{
***************
*** 515,522 ****
return;
}
! enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
! item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
if (!NILP (map) && SREF (item_string, 0) == '@')
{
--- 519,526 ----
return;
}
! enabled = AREF (item_properties, ITEM_PROPERTY_ENABLE);
! item_string = AREF (item_properties, ITEM_PROPERTY_NAME);
if (!NILP (map) && SREF (item_string, 0) == '@')
{
***************
*** 528,538 ****
}
push_menu_item (item_string, enabled, key,
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
! XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
/* Display a submenu using the toolkit. */
if (! (NILP (map) || NILP (enabled)))
--- 532,542 ----
}
push_menu_item (item_string, enabled, key,
! AREF (item_properties, ITEM_PROPERTY_DEF),
! AREF (item_properties, ITEM_PROPERTY_KEYEQ),
! AREF (item_properties, ITEM_PROPERTY_TYPE),
! AREF (item_properties, ITEM_PROPERTY_SELECTED),
! AREF (item_properties, ITEM_PROPERTY_HELP));
/* Display a submenu using the toolkit. */
if (! (NILP (map) || NILP (enabled)))
***************
*** 745,751 ****
/* Make that be the pane title of the first pane. */
if (!NILP (prompt) && menu_items_n_panes >= 0)
! XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
keymaps = 1;
}
--- 749,755 ----
/* Make that be the pane title of the first pane. */
if (!NILP (prompt) && menu_items_n_panes >= 0)
! ASET (menu_items, MENU_ITEMS_PANE_NAME, prompt);
keymaps = 1;
}
***************
*** 777,783 ****
/* Make the title be the pane title of the first pane. */
if (!NILP (title) && menu_items_n_panes >= 0)
! XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
keymaps = 1;
}
--- 781,787 ----
/* Make the title be the pane title of the first pane. */
if (!NILP (title) && menu_items_n_panes >= 0)
! ASET (menu_items, MENU_ITEMS_PANE_NAME, title);
keymaps = 1;
}
***************
*** 800,805 ****
--- 804,819 ----
}
#ifdef HAVE_MENUS
+ /* If resources from a previous popup menu exist yet, does nothing
+ until the `menu_free_timer' has freed them (see w32fns.c).
+ */
+ if (current_popup_menu)
+ {
+ discard_menu_items ();
+ UNGCPRO;
+ return Qnil;
+ }
+
/* Display them in a menu. */
BLOCK_INPUT;
***************
*** 808,816 ****
UNBLOCK_INPUT;
discard_menu_items ();
UNGCPRO;
- #endif /* HAVE_MENUS */
if (error_name) error (error_name);
return selection;
--- 822,830 ----
UNBLOCK_INPUT;
discard_menu_items ();
+ #endif /* HAVE_MENUS */
UNGCPRO;
if (error_name) error (error_name);
return selection;
***************
*** 981,1005 ****
i = 0;
while (i < f->menu_bar_items_used)
{
! if (EQ (XVECTOR (vector)->contents[i], Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (vector)->contents[i], Qt))
{
! prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
if ((int) (EMACS_INT) client_data == i)
--- 995,1019 ----
i = 0;
while (i < f->menu_bar_items_used)
{
! if (EQ (AREF (vector, i), Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (AREF (vector, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (vector, i), Qt))
{
! prefix = AREF (vector, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = AREF (vector, i + MENU_ITEMS_ITEM_VALUE);
/* The EMACS_INT cast avoids a warning. There's no problem
as long as pointers have enough bits to hold small integers. */
if ((int) (EMACS_INT) client_data == i)
***************
*** 1075,1081 ****
widget_value *wv;
{
if (! wv) return;
!
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
if (wv->contents && (wv->contents != (widget_value*)1))
--- 1089,1095 ----
widget_value *wv;
{
if (! wv) return;
!
wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
if (wv->contents && (wv->contents != (widget_value*)1))
***************
*** 1093,1114 ****
UNBLOCK_INPUT;
}
\f
! /* Return a tree of widget_value structures for a menu bar item
whose event type is ITEM_KEY (with string ITEM_NAME)
and whose contents come from the list of keymaps MAPS. */
! static widget_value *
! single_submenu (item_key, item_name, maps)
Lisp_Object item_key, item_name, maps;
{
- widget_value *wv, *prev_wv, *save_wv, *first_wv;
- int i;
- int submenu_depth = 0;
Lisp_Object length;
int len;
Lisp_Object *mapvec;
! widget_value **submenu_stack;
! int previous_items = menu_items_used;
int top_level_items = 0;
length = Flength (maps);
--- 1107,1124 ----
UNBLOCK_INPUT;
}
\f
! /* Set up data i menu_items for a menu bar item
whose event type is ITEM_KEY (with string ITEM_NAME)
and whose contents come from the list of keymaps MAPS. */
! static int
! parse_single_submenu (item_key, item_name, maps)
Lisp_Object item_key, item_name, maps;
{
Lisp_Object length;
int len;
Lisp_Object *mapvec;
! int i;
int top_level_items = 0;
length = Flength (maps);
***************
*** 1122,1129 ****
maps = Fcdr (maps);
}
- menu_items_n_panes = 0;
-
/* Loop over the given keymaps, making a pane for each map.
But don't make a pane that is empty--ignore that map instead. */
for (i = 0; i < len; i++)
--- 1132,1137 ----
***************
*** 1141,1149 ****
else
single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
}
! /* Create a tree of widget_value objects
! representing the panes and their items. */
submenu_stack
= (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
--- 1149,1171 ----
else
single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
}
+
+ return top_level_items;
+ }
!
! /* Create a tree of widget_value objects
! representing the panes and items
! in menu_items starting at index START, up to index END. */
!
! static widget_value *
! digest_single_submenu (start, end, top_level_items)
! int start, end;
! {
! widget_value *wv, *prev_wv, *save_wv, *first_wv;
! int i;
! int submenu_depth = 0;
! widget_value **submenu_stack;
submenu_stack
= (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
***************
*** 1161,1203 ****
and construct a tree of widget_value objects.
Ignore the panes and items made by previous calls to
single_submenu, even though those are also in menu_items. */
! i = previous_items;
! while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
! prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
}
#endif
pane_string = (NILP (pane_name)
--- 1183,1225 ----
and construct a tree of widget_value objects.
Ignore the panes and items made by previous calls to
single_submenu, even though those are also in menu_items. */
! i = start;
! while (i < end)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
prev_wv = 0;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (menu_items, i), Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
! else if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
#ifndef HAVE_MULTILINGUAL_MENU
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
#endif
pane_string = (NILP (pane_name)
***************
*** 1249,1261 ****
if (STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
--- 1271,1283 ----
if (STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
#endif /* not HAVE_MULTILINGUAL_MENU */
***************
*** 1320,1326 ****
HMENU menubar_widget = f->output_data.w32->menubar_widget;
Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
! int i;
/* We must not change the menubar when actually in use. */
if (f->output_data.w32->menubar_active)
--- 1342,1350 ----
HMENU menubar_widget = f->output_data.w32->menubar_widget;
Lisp_Object items;
widget_value *wv, *first_wv, *prev_wv = 0;
! int i, last_i;
! int *submenu_start, *submenu_end;
! int *submenu_top_level_items;
/* We must not change the menubar when actually in use. */
if (f->output_data.w32->menubar_active)
***************
*** 1333,1346 ****
else if (pending_menu_activation && !deep_p)
deep_p = 1;
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
- first_wv = wv;
-
if (deep_p)
{
/* Make a widget-value tree representing the entire menu trees. */
--- 1357,1362 ----
***************
*** 1384,1411 ****
items = FRAME_MENU_BAR_ITEMS (f);
- inhibit_garbage_collection ();
-
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
previous_menu_items_used * sizeof (Lisp_Object));
! /* Fill in the current menu bar contents. */
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
init_menu_items ();
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object key, string, maps;
! key = XVECTOR (items)->contents[i];
! string = XVECTOR (items)->contents[i + 1];
! maps = XVECTOR (items)->contents[i + 2];
if (NILP (string))
break;
! wv = single_submenu (key, string, maps);
if (prev_wv)
prev_wv->next = wv;
else
--- 1400,1457 ----
items = FRAME_MENU_BAR_ITEMS (f);
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
previous_menu_items_used * sizeof (Lisp_Object));
! /* Fill in menu_items with the current menu bar contents.
! This can evaluate Lisp code. */
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
+ submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+ submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
+ submenu_top_level_items
+ = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
init_menu_items ();
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object key, string, maps;
! last_i = i;
!
! key = AREF (items, i);
! string = AREF (items, i + 1);
! maps = AREF (items, i + 2);
if (NILP (string))
break;
! submenu_start[i] = menu_items_used;
!
! menu_items_n_panes = 0;
! submenu_top_level_items[i]
! = parse_single_submenu (key, string, maps);
!
! submenu_end[i] = menu_items_used;
! }
!
! finish_menu_items ();
!
! /* Convert menu_items into widget_value trees
! to display the menu. This cannot evaluate Lisp code. */
!
! wv = xmalloc_widget_value ();
! wv->name = "menubar";
! wv->value = 0;
! wv->enabled = 1;
! wv->button_type = BUTTON_TYPE_NONE;
! wv->help = Qnil;
! first_wv = wv;
!
! for (i = 0; i < last_i; i += 4)
! {
! wv = digest_single_submenu (submenu_start[i], submenu_end[i],
! submenu_top_level_items[i]);
if (prev_wv)
prev_wv->next = wv;
else
***************
*** 1416,1423 ****
prev_wv = wv;
}
- finish_menu_items ();
-
set_buffer_internal_1 (prev);
unbind_to (specpdl_count, Qnil);
--- 1462,1467 ----
***************
*** 1426,1432 ****
for (i = 0; i < previous_menu_items_used; i++)
if (menu_items_used == i
! || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
break;
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
--- 1470,1476 ----
for (i = 0; i < previous_menu_items_used; i++)
if (menu_items_used == i
! || (!EQ (previous_items[i], AREF (menu_items, i))))
break;
if (i == menu_items_used && i == previous_menu_items_used && i != 0)
{
***************
*** 1442,1451 ****
Windows takes care of this for normal string items, but
not for owner-drawn items or additional item-info. */
wv = first_wv->contents;
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object string;
! string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
wv->name = (char *) SDATA (string);
--- 1486,1495 ----
Windows takes care of this for normal string items, but
not for owner-drawn items or additional item-info. */
wv = first_wv->contents;
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object string;
! string = AREF (items, i + 1);
if (NILP (string))
break;
wv->name = (char *) SDATA (string);
***************
*** 1461,1472 ****
/* Make a widget-value tree containing
just the top level menu bar strings. */
items = FRAME_MENU_BAR_ITEMS (f);
! for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object string;
! string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
--- 1505,1524 ----
/* Make a widget-value tree containing
just the top level menu bar strings. */
+ wv = xmalloc_widget_value ();
+ wv->name = "menubar";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+
items = FRAME_MENU_BAR_ITEMS (f);
! for (i = 0; i < ASIZE (items); i += 4)
{
Lisp_Object string;
! string = AREF (items, i + 1);
if (NILP (string))
break;
***************
*** 1625,1631 ****
i = 0;
while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
--- 1677,1683 ----
i = 0;
while (i < menu_items_used)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
submenu_stack[submenu_depth++] = save_wv;
save_wv = prev_wv;
***************
*** 1633,1653 ****
first_pane = 1;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
first_pane = 0;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
--- 1685,1705 ----
first_pane = 1;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prev_wv = save_wv;
save_wv = submenu_stack[--submenu_depth];
first_pane = 0;
i++;
}
! else if (EQ (AREF (menu_items, i), Qt)
&& submenu_depth != 0)
i += MENU_ITEMS_PANE_LENGTH;
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
! else if (EQ (AREF (menu_items, i), Qt))
{
/* Create a new pane. */
Lisp_Object pane_name, prefix;
***************
*** 1658,1664 ****
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
}
#endif
pane_string = (NILP (pane_name)
--- 1710,1716 ----
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_SYSTEM (pane_name);
! ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
#endif
pane_string = (NILP (pane_name)
***************
*** 1713,1724 ****
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
}
#endif /* not HAVE_MULTILINGUAL_MENU */
--- 1765,1776 ----
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_SYSTEM (item_name);
! ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_SYSTEM (descrip);
! ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
#endif /* not HAVE_MULTILINGUAL_MENU */
***************
*** 1818,1848 ****
i = 0;
while (i < menu_items_used)
{
! if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
! prefix
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
i += 1;
else
{
! entry
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
if (menu_item_selection == i)
{
if (keymaps != 0)
--- 1870,1898 ----
i = 0;
while (i < menu_items_used)
{
! if (EQ (AREF (menu_items, i), Qnil))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
! else if (EQ (AREF (menu_items, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
! else if (EQ (AREF (menu_items, i), Qt))
{
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
! else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else
{
! entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == i)
{
if (keymaps != 0)
***************
*** 1903,1910 ****
{
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
! prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
--- 1953,1960 ----
{
Lisp_Object pane_name, prefix;
char *pane_string;
! pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
! prefix = AREF (menu_items, MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : (char *) SDATA (pane_name));
prev_wv = xmalloc_widget_value ();
***************
*** 1924,1934 ****
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, help;
! item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
! enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
! descrip
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
! help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
if (NILP (item_name))
{
--- 1974,1983 ----
/* Create a new item within current pane. */
Lisp_Object item_name, enable, descrip, help;
! item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
! enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
! descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
! help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
if (NILP (item_name))
{
***************
*** 1957,1963 ****
if (!NILP (descrip))
wv->key = (char *) SDATA (descrip);
wv->value = (char *) SDATA (item_name);
! wv->call_data = (void *) &XVECTOR (menu_items)->contents[i];
wv->enabled = !NILP (enable);
wv->help = Qnil;
prev_wv = wv;
--- 2006,2012 ----
if (!NILP (descrip))
wv->key = (char *) SDATA (descrip);
wv->value = (char *) SDATA (item_name);
! wv->call_data = (void *) &AREF (menu_items, i);
wv->enabled = !NILP (enable);
wv->help = Qnil;
prev_wv = wv;
***************
*** 2027,2042 ****
{
Lisp_Object entry;
! if (EQ (XVECTOR (menu_items)->contents[i], Qt))
{
! prefix
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry
! = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
if (menu_item_selection == i)
{
if (keymaps != 0)
--- 2076,2089 ----
{
Lisp_Object entry;
! if (EQ (AREF (menu_items, i), Qt))
{
! prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
! entry = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == i)
{
if (keymaps != 0)
***************
*** 2117,2127 ****
we can't deallocate the memory otherwise. */
if (get_menu_item_info)
{
! out_string = (char *) LocalAlloc (LPTR, strlen (wv->name) + 1);
#ifdef MENU_DEBUG
! DebPrint ("Menu: allocing %ld for owner-draw", info.dwItemData);
#endif
- strcpy (out_string, wv->name);
fuFlags = MF_OWNERDRAW | MF_DISABLED;
}
else
--- 2164,2174 ----
we can't deallocate the memory otherwise. */
if (get_menu_item_info)
{
! out_string = (char *) local_alloc (strlen (wv->name) + 1);
! strcpy (out_string, wv->name);
#ifdef MENU_DEBUG
! DebPrint ("Menu: allocing %ld for owner-draw", out_string);
#endif
fuFlags = MF_OWNERDRAW | MF_DISABLED;
}
else
***************
*** 2277,2283 ****
#ifdef MENU_DEBUG
DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
#endif
! LocalFree (info.dwItemData);
}
/* Recurse down submenus. */
--- 2324,2330 ----
#ifdef MENU_DEBUG
DebPrint ("Menu: freeing %ld for owner-draw", info.dwItemData);
#endif
! local_free (info.dwItemData);
}
/* Recurse down submenus. */
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
@ 2002-08-01 7:54 jasonr
0 siblings, 0 replies; 13+ messages in thread
From: jasonr @ 2002-08-01 7:54 UTC (permalink / raw)
Cc: emacs-devel
Are you able to install this yourself, or can someone else
do it for you? I am currently without an internet
connection (or phone line even) at home.
> from: David Ponce <david@dponce.com>
> date: Wed, 31 Jul 2002 23:37:05
> to: rms@gnu.org
> cc: emacs-devel@gnu.org
> subject: Re: NT Emacs crashes when selecting a menubar item
>
> Richard Stallman wrote:
>
> >I figured out how Lisp code was getting called during that loop.
> >xmenu.c had the same bug, so I fixed it there.
> >
> >Now we need a Windows hacker to adapt the same fix to w32menu.c.
> >Perhaps macmenu.c needs the same change.
> >
> >Thanks for figuring this out.
> >
> >
> Hi Richard,
>
> I adapted your changes from xmenu.c to the version of w32menu.c where
> I fixed another bug with popup menu, and generalized use of the macros
> AREF, ASET, ASIZE, to access vectors. Attached you will find a new
> diff. The change log is at end.
>
> I currently use this new version and can confirm that you fixed the bug
> :-)
>
> Thank you very much for your support!
> David
>
> ------------ Change Log:
>
> (local_heap, local_alloc, local_free): New macros.
> (malloc_widget_value, free_widget_value)
> (w32_free_submenu_strings): Use them.
>
> (push_submenu_start, push_submenu_end, push_left_right_boundary)
> (push_menu_pane, push_menu_item, single_keymap_panes)
> (single_menu_item, Fx_popup_menu, menubar_selection_callback)
> (single_submenu, set_frame_menubar)
> (w32_menu_show, w32_dialog_show): Use AREF, ASET, ASIZE.
>
> (Fx_popup_menu): Don't show pop up menu until preceding one is
> actually cleaned up. Moved UNGCPRO outside #ifdef HAVE_MENUS block.
>
> Changes adapted from xmenu.c
>
> (set_frame_menubar): First parse all submenus,
> then make widget_value trees from them.
> Don't allocate any widget_value objects
> until we are done with the parsing.
> (parse_single_submenu): New function.
> (digest_single_submenu): New function.
> (single_submenu): Function deleted, replaced by those two.
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: NT Emacs crashes when selecting a menubar item
@ 2002-08-01 11:39 David PONCE
0 siblings, 0 replies; 13+ messages in thread
From: David PONCE @ 2002-08-01 11:39 UTC (permalink / raw)
Cc: emacs-devel
> Are you able to install this yourself, or can someone else
> do it for you? I am currently without an internet
> connection (or phone line even) at home.
I can't do it myself. Richard?
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2002-08-01 11:39 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <3D2A791A00A0862A@mel-rta9.wanadoo.fr>
2002-07-31 21:57 ` NT Emacs crashes when selecting a menubar item Richard Stallman
2002-07-31 22:37 ` David Ponce
2002-08-01 11:39 David PONCE
-- strict thread matches above, loose matches on Subject: below --
2002-08-01 7:54 jasonr
2002-07-30 11:28 David PONCE
2002-07-24 18:55 David Ponce
2002-07-25 18:07 ` Richard Stallman
2002-07-26 12:30 ` David Ponce
2002-07-27 18:52 ` Richard Stallman
2002-07-28 16:56 ` David Ponce
2002-07-29 17:30 ` Richard Stallman
2002-07-29 18:16 ` David Ponce
2002-07-30 18:46 ` Richard Stallman
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).