Skip to content

Conversation

@simonchatts
Copy link
Contributor

On macOS, going to the plugin manager GUI panel can crash, due to an interaction with VoiceOver.

Example backtrace
thread #2, name = 'main', queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
      frame #0: 0x0000000109da5e2c libqcocoa.dylib`-[QMacAccessibilityElement initWithId:role:] + 328
      frame #1: 0x0000000109da6708 libqcocoa.dylib`+[QMacAccessibilityElement elementWithId:] + 72
      frame #2: 0x0000000109da3ed8 libqcocoa.dylib`QCocoaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent*) + 136
      frame #3: 0x00000001000724f4 .mscore-wrapped`muse::accessibility::AccessibilityController::reg(muse::accessibility::IAccessible*)
  + 908
      frame #4: 0x0000000101249128 .mscore-wrapped`muse::ui::AccessibleItem::componentComplete() + 60
      frame #5: 0x0000000101263430 .mscore-wrapped`muse::ui::AbstractNavigation::componentComplete() + 112
      frame #6: 0x00000001012467a0 .mscore-wrapped`muse::ui::NavigationControl::setPanel(muse::ui::NavigationPanel*) + 344
      frame #7: 0x00000001074d88bc QtQml`bool QObjectPointerBinding::compareAndSet)::'lambda'()>(QQmlMetaObject const&, QObject*, QQmlPropertyData const*,
  QFlags, QObjectPointerBinding::write(QV4::Value const&, bool,
  QFlags)::'lambda'() const&) const + 332
      frame #8: 0x00000001074d835c QtQml`QObjectPointerBinding::write(QV4::Value const&, bool, QFlags) +
  804
      frame #9: 0x00000001074d29e4 QtQml`QQmlBinding::doUpdate(QQmlJavaScriptExpression::DeleteWatcher const&,
  QFlags, QV4::Scope&) + 556
      frame #10: 0x00000001074d06f0 QtQml`QQmlBinding::update(QFlags) + 416
      frame #11: 0x000000010756c2b8 QtQml`QQmlObjectCreator::finalize(QQmlInstantiationInterrupt&) + 376
      frame #12: 0x00000001075340bc QtQml`QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt&) + 2412
      frame #13: 0x00000001075334f8 QtQml`QQmlEnginePrivate::incubate(QQmlIncubator&, QQmlRefPointer const&) + 364
      frame #14: 0x00000001074f21c8 QtQml`QQmlComponentPrivate::incubateObject(QQmlIncubator*, QQmlComponent*, QQmlEngine*,
  QQmlRefPointer const&, QQmlRefPointer const&) + 380
      frame #15: 0x0000000105468010 QtQmlModels`QQmlDelegateModelPrivate::object(QQmlListCompositor::Group, int,
  QQmlIncubator::IncubationMode) + 1604
      frame #16: 0x0000000106e565c4 QtQuick`QQuickItemViewPrivate::createItem(int, QQmlIncubator::IncubationMode) + 228
      frame #17: 0x0000000106e460c8 QtQuick`QQuickGridViewPrivate::addVisibleItems(double, double, double, double, bool) + 1032
      frame #18: 0x0000000106e56ebc QtQuick`QQuickItemViewPrivate::refill(double, double) + 528
      frame #19: 0x0000000106e55ab0 QtQuick`QQuickItemView::componentComplete() + 368
      frame #20: 0x000000010756c6bc QtQml`QQmlObjectCreator::finalize(QQmlInstantiationInterrupt&) + 1404
      frame #21: 0x00000001075340bc QtQml`QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt&) + 2412
      frame #22: 0x00000001075334f8 QtQml`QQmlEnginePrivate::incubate(QQmlIncubator&, QQmlRefPointer const&) + 364
      frame #23: 0x00000001074f1f4c QtQml`QQmlComponent::create(QQmlIncubator&, QQmlContext*, QQmlContext*) + 772
      frame #24: 0x0000000106b7bd94 QtQuick`QQuickLoaderPrivate::_q_sourceLoaded() + 620
      frame #25: 0x00000001074d88bc QtQml`bool QObjectPointerBinding::compareAndSet)::'lambda'()>(QQmlMetaObject const&, QObject*, QQmlPropertyData const*,
  QFlags, QObjectPointerBinding::write(QV4::Value const&, bool,
  QFlags)::'lambda'() const&) const + 332
      frame #26: 0x00000001074d835c QtQml`QObjectPointerBinding::write(QV4::Value const&, bool, QFlags) +
  804
      frame #27: 0x00000001074d29e4 QtQml`QQmlBinding::doUpdate(QQmlJavaScriptExpression::DeleteWatcher const&,
  QFlags, QV4::Scope&) + 556
      frame #28: 0x00000001074d06f0 QtQml`QQmlBinding::update(QFlags) + 416
      frame #29: 0x00000001075623f4 QtQml`QQmlNotifier::emitNotify(QQmlNotifierEndpoint*, void**) + 568
      frame #30: 0x0000000107a8163c QtCore`void doActivate(QObject*, int, void**) + 156
      frame #31: 0x000000010761ca30 QtQml`QQmlVMEMetaObject::metaCall(QObject*, QMetaObject::Call, int, void**) + 5284
      frame #32: 0x00000001074d525c QtQml`QQmlPropertyData::writeProperty(QObject*, void*, QFlags) const +
  96
      frame #33: 0x0000000107586f40 QtQml`QQmlPropertyPrivate::write(QObject*, QQmlPropertyData const&, QVariant const&,
  QQmlRefPointer const&, QFlags) + 2132
      frame #34: 0x00000001074218c4 QtQml`QV4::QObjectWrapper::setProperty(QV4::ExecutionEngine*, QObject*, QQmlPropertyData const*,
  QV4::Value const&) + 3776
      frame #35: 0x0000000107420994 QtQml`QV4::QObjectWrapper::setQmlProperty(QV4::ExecutionEngine*, QQmlRefPointer
  const&, QObject*, QV4::String*, QFlags, QV4::Value const&) + 280
      frame #36: 0x00000001074237ec QtQml`QV4::QObjectWrapper::virtualPut(QV4::Managed*, QV4::PropertyKey, QV4::Value const&,
  QV4::Value*) + 700
      frame #37: 0x0000000107401e6c QtQml`QV4::Object::virtualResolveLookupSetter(QV4::Object*, QV4::ExecutionEngine*, QV4::Lookup*,
  QV4::Value const&) + 396
      frame #38: 0x000000010748e14c QtQml`QV4::Moth::VME::interpret(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*, char const*) + 2776
      frame #39: 0x000000010748d5a0 QtQml`QV4::Moth::VME::exec(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*) + 304
      frame #40: 0x00000001073df11c QtQml`qfoDoCall(QV4::JavaScriptFunctionObject const*, QV4::Value const*, QV4::Value const*, int) +
  352
      frame #41: 0x000000010748e67c QtQml`QV4::Moth::VME::interpret(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*, char const*) + 4104
      frame #42: 0x000000010748d5a0 QtQml`QV4::Moth::VME::exec(QV4::JSTypesStackFrame*, QV4::ExecutionEngine*) + 304
      frame #43: 0x00000001073d6cb8 QtQml`QV4::doCall(QV4::Function*, QV4::Value const*, QV4::Value const*, int,
  QV4::ExecutionContext*) + 324
      frame #44: 0x00000001073d6440 QtQml`QV4::Function::call(QObject*, void**, QMetaType const*, int, QV4::ExecutionContext*) + 544
      frame #45: 0x0000000107538630 QtQml`QQmlJavaScriptExpression::evaluate(void**, QMetaType const*, int) + 272
      frame #46: 0x00000001074dc6e8 QtQml`QQmlBoundSignalExpression::evaluate(void**) + 976
      frame #47: 0x00000001074dcd18 QtQml`QQmlBoundSignal_callback(QQmlNotifierEndpoint*, void**) + 332
      frame #48: 0x00000001075623f4 QtQml`QQmlNotifier::emitNotify(QQmlNotifierEndpoint*, void**) + 568
      frame #49: 0x0000000107a8163c QtCore`void doActivate(QObject*, int, void**) + 156
      frame #50: 0x000000010761ca30 QtQml`QQmlVMEMetaObject::metaCall(QObject*, QMetaObject::Call, int, void**) + 5284
      frame #51: 0x0000000107428414 QtQml`QV4::CallMethod(QQmlObjectOrGadget const&, int, QMetaType, int, QMetaType const*,
  QV4::ExecutionEngine*, QV4::CallData*, QMetaObject::Call) + 6040
      frame #52: 0x00000001074262cc QtQml`QV4::QObjectMethod::callPrecise(QQmlObjectOrGadget const&, QQmlPropertyData const&,
      frame #58: 0x0000000107538630 QtQml`QQmlJavaScriptExpression::evaluate(void**, QMetaType const*, int) + 272
      frame #59: 0x00000001074dc468 QtQml`QQmlBoundSignalExpression::evaluate(void**) + 336
      frame #60: 0x00000001074dcd18 QtQml`QQmlBoundSignal_callback(QQmlNotifierEndpoint*, void**) + 332
      frame #61: 0x00000001075623f4 QtQml`QQmlNotifier::emitNotify(QQmlNotifierEndpoint*, void**) + 568
      frame #62: 0x0000000107a8163c QtCore`void doActivate(QObject*, int, void**) + 156
      frame #63: 0x00000001094fb39c QtQuickTemplates2`QQuickAbstractButtonPrivate::handleRelease(QPointF const&, unsigned long) + 260
      frame #64: 0x0000000109521ff0 QtQuickTemplates2`QQuickControl::mouseReleaseEvent(QMouseEvent*) + 76
      frame #65: 0x0000000106b5a2cc QtQuick`QQuickItem::event(QEvent*) + 376
      frame #70: 0x0000000106d25ecc QtQuick`QQuickDeliveryAgentPrivate::deliverUpdatedPoints(QPointerEvent*) + 620
      frame #71: 0x0000000106d20d74 QtQuick`QQuickDeliveryAgentPrivate::deliverPointerEvent(QPointerEvent*) + 2428
      frame #72: 0x0000000106d1ed10 QtQuick`QQuickDeliveryAgentPrivate::handleMouseEvent(QMouseEvent*) + 1324
      frame #73: 0x0000000106d1e3ec QtQuick`QQuickDeliveryAgent::event(QEvent*) + 108
      frame #81: 0x0000000109d28a44 libqcocoa.dylib`QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void*) + 532
      frame #82: 0x0000000191eaea64 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
      frame #83: 0x0000000191eae9f8 CoreFoundation`__CFRunLoopDoSource0 + 172
      frame #84: 0x0000000191eae764 CoreFoundation`__CFRunLoopDoSources0 + 232
      frame #90: 0x0000000195dcca34 AppKit`_DPSNextEvent + 684
      frame #91: 0x000000019676b940 AppKit`-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 688
      frame #92: 0x0000000195dbfbe4 AppKit`-[NSApplication run] + 480
      frame #93: 0x0000000109d25ec4 libqcocoa.dylib`QCocoaEventDispatcher::processEvents(QFlags) + 2396
      frame #94: 0x0000000107a2f2bc QtCore`QEventLoop::exec(QFlags) + 592
      frame #95: 0x0000000107a23e64 QtCore`QCoreApplication::exec() + 144
      frame #96: 0x0000000100010cd4 .mscore-wrapped`main + 1040
      frame #97: 0x0000000191a22b98 dyld`start + 6076

Directly invoking AbstractNavigation::componentComplete() skips the
override where NavigationControl::componentComplete() first asks its
NavigationPanel to finish initialization before finalizing the control
. When
VoiceOver queries the plugin list, the control’s accessibility object can be
registered, even though its panel (and section) haven't been, so the first
QAccessibleEvent has a nullptr parent. libqcocoa can then dereference that when
constructing QMacAccessibilityElement.

Simply removing the class override fixes the problem on my mac.

  • I signed the CLA
  • The title of the PR describes the problem it addresses
  • Each commit's message describes its purpose and effects, and references the issue it resolves
  • If changes are extensive, there is a sequence of easily reviewable commits
  • The code in the PR follows the coding rules
  • There are no unnecessary changes
  • The code compiles and runs on my machine, preferably after each commit individually
  • I created a unit test or vtest to verify the changes I made (if applicable)

On macOS, going to the plugin manager could crash (EXC_BAD_ACCESS). This was
because directly invoking AbstractNavigation::componentComplete() bypassed the
override where NavigationControl::componentComplete() first asks its
NavigationPanel to finish initialization before finalizing the control. When
VoiceOver queried the plugin list, the control’s accessibility object was
registered, even though its panel (and section) hadn’t been, so the first
QAccessibleEvent had a nullptr parent.  libqcocoa then dereferenced that when
constructing QMacAccessibilityElement.
@cbjeukendrup
Copy link
Member

Looks related to this Sentry entry: https://sentry.musescore.com/organizations/sentry/issues/278/ (accessible for the internal team only)
Hence adding it to the 4.6.4 project

@DmitryArefiev
Copy link
Contributor

@simonchatts @Eism Tested on Mac13.7.8. On Plugins page when navigating plugin settings, VO doesn't speak Edit shortcut and Disable buttons (this is regression comparing with previous master builds when there was no crash on Plugins page with VO)

Screen.Recording.2025-11-17.at.17.00.56.2.mov

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants