Details
Description
I’m getting seg faults running an app on macOS that are in some way related to QMenus and Qt setting an empty menu through the AppKit interface. Those problems only appear when the app is frozen (through PyInstaller) or compiled (with Nuitka) and when started from Finder or Launchpad. They do not occur when the App is run from a Terminal.
Here’s a minimum example:
import sys from PySide6.QtWidgets import QApplication from PySide6.QtCore import Qt from PySide6.QtWidgets import ( QDockWidget, QMainWindow, QMenu, QMenuBar, ) class MainWindow(QMainWindow): def __init__(self) -> None: super().__init__() self.setWindowTitle("TestApp") self.menu_bar = QMenuBar(self) self.view_menu = QMenu(self.menu_bar) self.setMenuBar(self.menu_bar) # Give this menu any other title and it will work: self.view_menu.setTitle("View") self.menu_bar.addAction(self.view_menu.menuAction()) self.dock_widget = QDockWidget(self) self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_widget) self.dock_widget.setWindowTitle("Dock Widget") self.view_menu.addAction(self.dock_widget.toggleViewAction()) if __name__ == "__main__": app = QApplication(sys.argv) main_window = MainWindow() main_window.show() sys.exit(app.exec())
Attached to this bug report are a pyproject.toml and a poetry.lock with the exact package versions I used. The app can be compiled with this command:
python3 -m nuitka --enable-plugin=pyside6 --standalone --disable-console --macos-create-app-bundle crash_app.py
When running the app (e.g., from Finder with a double click), perform the following steps to get the segfault:
- Grad the QDockWidget and move it out of the app so that it is floating
- Click on View → Dock Widget
This will produce the crash. There are other ways that will work (like moving the app to the background and bring it back as active app). Nevertheless, the two steps described work 100% for me.
Here’s the relevant part of the macOS crash report (full report is attached):
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libsystem_kernel.dylib 0x18843511c __pthread_kill + 8 1 libsystem_pthread.dylib 0x18846ccc0 pthread_kill + 288 2 libsystem_c.dylib 0x18837ca40 abort + 180 3 libc++abi.dylib 0x1884246d8 abort_message + 132 4 libc++abi.dylib 0x1884147c8 demangling_terminate_handler() + 348 5 libobjc.A.dylib 0x1880bf894 _objc_terminate() + 144 6 libc++abi.dylib 0x188423a9c std::__terminate(void (*)()) + 16 7 libc++abi.dylib 0x188426a48 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 36 8 libc++abi.dylib 0x1884269f4 __cxa_throw + 140 9 libobjc.A.dylib 0x1880b601c objc_exception_throw + 420 10 Foundation 0x18970547c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 188 11 AppKit 0x18bd158a0 -[NSMenu itemAtIndex:] + 156 12 AppKit 0x18bd152b4 -[NSApplication(NSWindowsMenu) setWindowsMenu:] + 124 13 libqcocoa.dylib 0x1099a02c8 QCocoaMenuBar::insertWindowMenu() + 264 (qcocoamenubar.mm:352) 14 libqcocoa.dylib 0x10999eba0 QCocoaMenuBar::updateMenuBarImmediately() + 1476 (qcocoamenubar.mm:331) 15 QtCore 0x104a15480 void doActivate<false>(QObject*, int, void**) + 1384 (qobject.cpp:4004) 16 QtGui 0x1060cb258 QGuiApplication::focusWindowChanged(QWindow*) + 24 (moc_qguiapplication.cpp:587) [inlined]
After talking to AppKit developers, this occurs because Qt tries to set an empty NSMenu. The relevant part is line 11 where AppKit tries to find an item in the NSMenu.
Strange enough, this does only happen, if the menu is named View (where macOS will add the “Enter Full Screen” entry), but not if I give it some other name.
Attachments
For Gerrit Dashboard: PYSIDE-2525 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
518061,3 | macOS: Work around [NSApplication setWindowsMenu:] out of bound access | dev | qt/qtbase | Status: MERGED | +2 | 0 |
518680,2 | macOS: Work around [NSApplication setWindowsMenu:] out of bound access | 6.6 | qt/qtbase | Status: MERGED | +2 | 0 |
519128,2 | macOS: Work around [NSApplication setWindowsMenu:] out of bound access | tqtc/lts-6.5 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |