bug#81610: 30.2; [PATCH] NS; NSRangeException when enabling tool-bar-mode
Eli Zaretskii <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
> Cc: [email protected] > Date: Wed, 12 Aug 2026 16:54:06 +0300 > From: Yavor Doganov <[email protected]> > > If I customize the tool-bar-mode variable to nil then the toolbar is > not displayed, as expected. However, if I enable it explicitly with > the interactive command, an exception is thrown: a dialog "Critical > Error in emacs" appears containing "NSRangeException: Index 0 is out > of range 0 (in 'objectAtIndex:')". Emacs then aborts. > > Steps to reproduce: > > 1. emacs -Q --eval "(tool-bar-mode -1)" > 2. M-x tool-bar-mode RET > > Backtrace and proposed patch below based on the master branch. > > In GNU Emacs 30.2 (build 2, x86_64-pc-linux-gnu, NS > gnustep-gui-0.32.0) of 2026-07-04, modified by Debian built on > patilan > Windowing system distributor 'GNU', version 10.3.32 > System Description: Debian GNU/Linux forky/sid > > Configured using: > 'configure --build x86_64-linux-gnu --prefix=/usr > --sharedstatedir=/var/lib --libexecdir=/usr/libexec > --localstatedir=/var/lib --infodir=/usr/share/info > --mandir=/usr/share/man --with-libsystemd --with-pop=yes > --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/30.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/30.2/site-lisp:/usr/share/emacs/site-lisp > --with-sound=alsa --without-gconf --with-mailutils --build > x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib > --libexecdir=/usr/libexec --localstatedir=/var/lib > --infodir=/usr/share/info --mandir=/usr/share/man --with-libsystemd > --with-pop=yes > --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/30.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/30.2/site-lisp:/usr/share/emacs/site-lisp > --with-sound=alsa --without-gconf --with-mailutils --with-ns > --disable-ns-self-contained --without-gif --without-jpeg > --without-png --without-rsvg --without-tiff --without-webp 'CFLAGS=-g > -O2 -Werror=implicit-function-declaration > -ffile-prefix-map=/build/reproducible-path/emacs-30.2+1=. -fstack-protector-strong > -fstack-clash-protection -Wformat -Werror=format-security > -fcf-protection -Wall' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2' > LDFLAGS=-Wl,-z,relro' > > Configured features: > ACL DBUS GMP GNUTLS GPM LCMS2 LIBSELINUX LIBSYSTEMD LIBXML2 MODULES > NATIVE_COMP NOTIFY INOTIFY NS PDUMPER SECCOMP SOUND SQLITE3 THREADS > TOOLKIT_SCROLL_BARS TREE_SITTER XIM ZLIB > > (gdb) break -[NSException raise] > ❌️ Function "-[NSException raise]" not defined. > Make breakpoint pending on future shared library load? (y or [n]) y > Breakpoint 1 (-[NSException raise]) pending. > (gdb) r -Q --eval "(tool-bar-mode -1)" > Starting program: /home/yavor/src/emacs/src/emacs -Q --eval "(tool-bar-mode -1)" > [Thread debugging using libthread_db enabled] > Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1". > ⚠️ warning: Corrupted shared library list: 0x5555564e04b0 != 0x5555564df930 > [New Thread 0x7fffe8d5e6c0 (LWP 246730)] > > Thread 1 "emacs" hit Breakpoint 1, -[NSException raise] (self=0x5555574f8030, > _cmd=0x7ffff758d640 <_OBJC_SELECTOR_TABLE+128>) > at ./Source/NSException.m:1602 > ⚠️ warning: 1602 ./Source/NSException.m: Няма такъв файл или директория > (gdb) bt > #0 -[NSException raise] > (self=0x5555574f8030, _cmd=0x7ffff758d640 <_OBJC_SELECTOR_TABLE+128>) > at ./Source/NSException.m:1602 > #1 0x00007ffff71c02b4 in -[GSArray objectAtIndex:] > (self=0x555557b78bc0, _cmd=<optimized out>, index=0) > at ./Source/GSArray.m:355 > #2 0x00007ffff7c1dddd in -[NSToolbar _removeItemAtIndex:broadcast:] > (self=0x555557a87500, _cmd=<optimized out>, index=0, broadcast=0 '\000') > at ./Source/NSToolbar.m:1270 > #3 0x00007ffff7c1dfed in -[NSToolbar _removeItemAtIndex:broadcast:] > (self=0x555557fb5980, _cmd=<optimized out>, index=0, broadcast=<optimized out>) at ./Source/NSToolbar.m:1284 > #4 0x0000555555851b79 in -[EmacsToolbar clearAll] > (self=0x555557fb5980, _cmd=<optimized out>) at nsmenu.m:1310 > #5 0x00005555558569de in update_frame_tool_bar_1 > (f=0x5555560725a0, toolbar=0x555557fb5980) at nsmenu.m:1133 > #6 0x0000555555662e44 in redisplay_window > (window=0x5555560f1105, just_this_one_p=just_this_one_p@entry=false) > at xdisp.c:21545 > #7 0x0000555555663adb in redisplay_window_0 (window=<optimized out>) > at xdisp.c:18531 > #8 0x0000555555773a29 in internal_condition_case_1 > (bfun=bfun@entry=0x555555663ab0 <redisplay_window_0>, arg=0x5555560f1105, handlers=<optimized out>, hfun=hfun@entry=0x5555556149b0 <redisplay_window_error>) at eval.c:1736 > #9 0x0000555555611c85 in redisplay_windows (window=0x5555560f1105) > at xdisp.c:18500 > #10 0x0000555555647cc0 in redisplay_internal () at xdisp.c:17917 > #11 0x0000555555649b75 in redisplay () at xdisp.c:17063 > #12 0x00005555556f0582 in read_char > (commandflag=<optimized out>, map=map@entry=0x7fffecf61563, prev_event=<optimized out>, used_mouse_menu=used_mouse_menu@entry=0x7fffffffd76b, end_time=end_time@entry=0x0) at keyboard.c:2711 > #13 0x00005555556f35e3 in read_key_sequence > (keybuf=keybuf@entry=0x7fffffffd8b0, prompt=prompt@entry=0x0, dont_downcase_last=dont_downcase_last@entry=false, can_return_switch_frame=can_return_switch_frame@entry=true, fix_current_buffer=fix_current_buffer@entry=true, prevent_redisplay=prevent_redisplay@entry=false, disable_text_conversion_p=false) > at keyboard.c:11224 > #14 0x00005555556f5754 in command_loop_1 () at keyboard.c:1424 > #15 0x00005555557739a4 in internal_condition_case > (bfun=bfun@entry=0x5555556f55a0 <command_loop_1>, handlers=handlers@entry=0x90, hfun=hfun@entry=0x5555556e7b30 <cmd_error>) at eval.c:1712 > #16 0x00005555556df366 in command_loop_2 (handlers=0x90) at keyboard.c:1163 > #17 0x00005555557738fe in internal_catch > (tag=tag@entry=0x12270, func=func@entry=0x5555556df340 <command_loop_2>, arg=arg@entry=0x90) at eval.c:1392 > #18 0x00005555556df303 in command_loop () at keyboard.c:1141 > #19 0x00005555556e76e1 in recursive_edit_1 () at keyboard.c:749 > #20 0x00005555556e7a68 in Frecursive_edit () at keyboard.c:832 > #21 0x00005555555f1de8 in main (argc=<optimized out>, argv=<optimized out>) > at emacs.c:2635 > (gdb) fr 3 > #3 0x00007ffff7c1dfed in -[NSToolbar _removeItemAtIndex:broadcast:] ( > self=0x555557fb5980, _cmd=<optimized out>, index=0, > broadcast=<optimized out>) at ./Source/NSToolbar.m:1284 > ⚠️ warning: 1284 ./Source/NSToolbar.m: Няма такъв файл или директория > (gdb) po self > <EmacsToolbar: 0x555557fb5980> > (gdb) po _items > ("<<NSToolbarItem: 0x555557fb5210> - <5864062930753Open>>", "<<NSToolbarItem: 0x555557fb4ac0> - <5864062916976Open Directory>>", "<<NSToolbarItem: 0x555557fb42f0> - <5864062922955Close>>", "<<NSToolbarItem: 0x555557fb3b20> - <5864062924951Save>>", "<<NSToolbarItem: 0x555557fb3350> - <5864062937190Undo>>", "<<NSToolbarItem: 0x555557fb2b80> - <5864062939314Cut>>", "<<NSToolbarItem: 0x555557fb23b0> - <5864062940411Copy>>", "<<NSToolbarItem: 0x555557fb1bc0> - <5864063816493Paste>>", "<<NSToolbarItem: 0x555557fb13f0> - <5864064151308Search>>") > (gdb) down > #2 0x00007ffff7c1dddd in -[NSToolbar _removeItemAtIndex:broadcast:] ( > self=0x555557a87500, _cmd=<optimized out>, index=0, broadcast=0 '\000') > at ./Source/NSToolbar.m:1270 > 1270 in ./Source/NSToolbar.m > (gdb) po self > <EmacsToolbar: 0x555557a87500> > (gdb) po _items > () > > Notice that in GDB frames 2 and 3 there are two distinct EmacsToolbar > instances for a single Emacs frame. The one from GDB frame 2, > 0x555557a87500, is a "parasite" object: it is initialized at frame > creation and toolbar items are never insterted in it. > > GNUstep's NSToolbar implementation of -removeItemAtIndex: (called from > EmacsToolbar -clearAll, nsmenu.m:1310) calls the private method > -_removeItemAtIndex:broadcast: which calls itself recursively, > dispatching the method call to all instances of the same class with > identical identifiers (see the TRANSMIT macro definition in > gnustep-gui/Source/NSToolbar.m:1205). The goal here is to update the > toolbars of the app's other windows ("frames" in Emacs terminology) if > the identifiers match. > > Because this first EmacsToolbar instance doesn't have any toolbar > items, an exception occurs. Alan, any comments to the patch? Because it's definitely macOS-specific.