8000 macOS OpenGL crash race condition · Issue #108 · CadQuery/CQ-editor · GitHub
[go: up one dir, main page]

Skip to content

macOS OpenGL crash race condition #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
michaelgale opened this issue Jan 6, 2020 · 3 comments
Open

macOS OpenGL crash race condition #108

michaelgale opened this issue Jan 6, 2020 · 3 comments

Comments

@michaelgale
Copy link

During my attempts to build standalone binaries of the CQ-Editor for macOS, I have discovered at least two mechanisms for the app to crash at launch. Both are related to OpenGL not being initialized. The first mechanism might be related to #106 and involve a race condition:

  1. MainWindow's __init__ method calls self.components['object_tree'].addLines()
  2. This triggers an event self.sigObjectsAdded.emit(ais_list)
  3. which is responded by def display_many(self,ais_list,fit=None): in viewer.py
  4. This calls context.Display(ais) which resolves to the Display method of OCC.Display.qtDisplay.qtViewer3d which resolves to _AIS.AIS_InteractiveContext_Display(self, *args)

This last call to AIS display occurs before the thread responsible for initializing the OpenGL driver and display context. We infer this is the case since we see no evidence of the initialization completed (usually a console message saying something about the layer manager).

There are definitely non thread safe conditions being established at application launch, especially the call to add the axis lines. When this is commented out, the app may or may not crash depending on the launch context (i.e. direct from terminal, lldb, or via the macOS launchd when initiated by the Finder or the terminal open command).

The support stack trace is as follows...

* thread #1: tid = 0x34ddc4, 0x00007fff670247fa libsystem_kernel.dylib`__pthread_kill + 10, name = 'ZMQbg/1', queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  thread #2: tid = 0x34de09, 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #5: tid = 0x34df34, 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #6: tid = 0x34df44, 0x00007fff67020ce6 libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #7: tid = 0x34df48, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
  thread #8: tid = 0x34df49, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
  thread #9: tid = 0x34df4a, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
(lldb) thread list all
Process 94969 stopped
* thread #1: tid = 0x34ddc4, 0x00007fff670247fa libsystem_kernel.dylib`__pthread_kill + 10, name = 'ZMQbg/1', queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  thread #2: tid = 0x34de09, 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #5: tid = 0x34df34, 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #6: tid = 0x34df44, 0x00007fff67020ce6 libsystem_kernel.dylib`__psynch_cvwait + 10
  thread #7: tid = 0x34df48, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
  thread #8: tid = 0x34df49, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
  thread #9: tid = 0x34df4a, 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
(lldb) thread backtrace all
* thread #1, name = 'ZMQbg/1', queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff670247fa libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff670e1bc1 libsystem_pthread.dylib`pthread_kill + 432
    frame #2: 0x00007fff66faba1c libsystem_c.dylib`abort + 120
    frame #3: 0x00007fff670a1647 libsystem_malloc.dylib`malloc_vreport + 548
    frame #4: 0x00007fff670
8000
a440e libsystem_malloc.dylib`malloc_report + 151
    frame #5: 0x000000010d851d69 libc++abi.1.dylib`__cxa_end_catch + 137
    frame #6: 0x000000012d3e45a4 _AIS.so`_wrap_AIS_InteractiveContext_Display__SWIG_0(_object*, int, _object**) + 1332
    frame #7: 0x000000012d2ad902 _AIS.so`_wrap_AIS_InteractiveContext_Display(_object*, _object*) + 98
    frame #8: 0x000000010192bff3 libpython3.7m.dylib`_PyMethodDef_RawFastCallKeywords + 259
    frame #9: 0x000000010192bbd2 libpython3.7m.dylib`_PyObject_FastCallKeywords + 306
    frame #10: 0x0000000101a34244 libpython3.7m.dylib`call_function + 708
    frame #11: 0x0000000101a2b3d5 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7893
    frame #12: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #13: 0x000000010192afd1 libpython3.7m.dylib`_PyFunction_FastCallDict + 481
    frame #14: 0x000000010192ca84 libpython3.7m.dylib`_PyObject_Call_Prepend + 164
    frame #15: 0x000000010192e494 libpython3.7m.dylib`method_call + 36
    frame #16: 0x000000010192c496 libpython3.7m.dylib`PyObject_Call + 246
    frame #17: 0x00000001082dd007 QtCore.so`PyQtSlot::call(_object*, _object*) const + 39
    frame #18: 0x00000001082dcf16 QtCore.so`PyQtSlot::invoke(void**, _object*, void*, bool) const + 374
    frame #19: 0x00000001082dcfac QtCore.so`PyQtSlot::invoke(void**, _object*, void*) const + 12
    frame #20: 0x00000001082dfe0b QtCore.so`qt_metacall_worker(_sipSimpleWrapper*, _typeobject*, _sipTypeDef*, QMetaObject::Call, int, void**) + 683
    frame #21: 0x00000001082dfb32 QtCore.so`qpycore_qobject_qt_metacall(_sipSimpleWrapper*, _sipTypeDef*, QMetaObject::Call, int, void**) + 66
    frame #22: 0x000000010586b37d QtCore`QMetaObject::activate(QObject*, int, int, void**) + 1773
    frame #23: 0x00000001082d971f QtCore.so`pyqtBoundSignal_emit(_object*, _object*) + 655
    frame #24: 0x000000010192bff3 libpython3.7m.dylib`_PyMethodDef_RawFastCallKeywords + 259
    frame #25: 0x0000000101936885 libpython3.7m.dylib`_PyMethodDescr_FastCallKeywords + 85
    frame #26: 0x0000000101a34274 libpython3.7m.dylib`call_function + 756
    frame #27: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #28: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #29: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #30: 0x0000000101a2b3d5 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7893
    frame #31: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #32: 0x000000010192afd1 libpython3.7m.dylib`_PyFunction_FastCallDict + 481
    frame #33: 0x000000010192ca84 libpython3.7m.dylib`_PyObject_Call_Prepend + 164
    frame #34: 0x000000010199431a libpython3.7m.dylib`slot_tp_init + 298
    frame #35: 0x000000010199da17 libpython3.7m.dylib`type_call + 295
    frame #36: 0x000000010192bd53 libpython3.7m.dylib`_PyObject_FastCallKeywords + 691
    frame #37: 0x0000000101a34244 libpython3.7m.dylib`call_function + 708
    frame #38: 0x0000000101a2b466 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 8038
    frame #39: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #40: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #41: 0x0000000101a2b466 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 8038
    frame #42: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #43: 0x0000000101a28370 libpython3.7m.dylib`PyEval_EvalCode + 48
    frame #44: 0x0000000100003116 CQ-Editor`___lldb_unnamed_symbol20$$CQ-Editor + 342
    frame #45: 0x0000000100003621 CQ-Editor`___lldb_unnamed_symbol27$$CQ-Editor + 385
    frame #46: 0x0000000100001de4 CQ-Editor`___lldb_unnamed_symbol1$$CQ-Editor + 52
  thread #2
    frame #0: 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff670de760 libsystem_pthread.dylib`_pthread_wqthread + 390
    frame #2: 0x00007fff670dd827 libsystem_pthread.dylib`start_wqthread + 15
  thread #5
    frame #0: 0x00007fff6701f92e libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x00007fff670de760 libsystem_pthread.dylib`_pthread_wqthread + 390
    frame #2: 0x00007fff670dd827 libsystem_pthread.dylib`start_wqthread + 15
  thread #6
    frame #0: 0x00007fff67020ce6 libsystem_kernel.dylib`__psynch_cvwait + 10
    frame #1: 0x00007fff670e2185 libsystem_pthread.dylib`_pthread_cond_wait + 701
    frame #2: 0x0000000101a8ae88 libpython3.7m.dylib`PyThread_acquire_lock_timed + 440
    frame #3: 0x0000000101aeb9af libpython3.7m.dylib`acquire_timed + 431
    frame #4: 0x0000000101aebaed libpython3.7m.dylib`lock_PyThread_acquire_lock + 61
    frame #5: 0x000000010192c1e3 libpython3.7m.dylib`_PyMethodDef_RawFastCallKeywords + 755
    frame #6: 0x0000000101936885 libpython3.7m.dylib`_PyMethodDescr_FastCallKeywords + 85
    frame #7: 0x0000000101a34274 libpython3.7m.dylib`call_function + 756
    frame #8: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #9: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #10: 0x000000010192bed6 libpython3.7m.dylib`_PyFunction_FastCallKeywords + 230
    frame #11: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #12: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #13: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #14: 0x000000010192bed6 libpython3.7m.dylib`_PyFunction_FastCallKeywords + 230
    frame #15: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #16: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #17: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #18: 0x0000000101a2b745 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 8773
    frame #19: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #20: 0x000000010192bed6 libpython3.7m.dylib`_PyFunction_FastCallKeywords + 230
    frame #21: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #22: 0x0000000101a2b466 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 8038
    frame #23: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #24: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #25: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #26: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #27: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #28: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #29: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #30: 0x000000010192ca84 libpython3.7m.dylib`_PyObject_Call_Prepend + 164
    frame #31: 0x000000010192e494 libpython3.7m.dylib`method_call + 36
    frame #32: 0x000000010192c496 libpython3.7m.dylib`PyObject_Call + 246
    frame #33: 0x0000000101aeae19 libpython3.7m.dylib`t_bootstrap + 169
    frame #34: 0x0000000101a8aa57 libpython3.7m.dylib`pythread_wrapper + 39
    frame #35: 0x00007fff670e1e65 libsystem_pthread.dylib`_pthread_start + 148
    frame #36: 0x00007fff670dd83b libsystem_pthread.dylib`thread_start + 15
  thread #7
    frame #0: 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
    frame #1: 0x000000012fa871fb libzmq.5.dylib`zmq::kqueue_t::loop() + 283
    frame #2: 0x000000012fab76df libzmq.5.dylib`thread_routine(void*) + 63
    frame #3: 0x00007fff670e1e65 libsystem_pthread.dylib`_pthread_start + 148
    frame #4: 0x00007fff670dd83b libsystem_pthread.dylib`thread_start + 15
  thread #8
    frame #0: 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
    frame #1: 0x000000012fa871fb libzmq.5.dylib`zmq::kqueue_t::loop() + 283
    frame #2: 0x000000012fab76df libzmq.5.dylib`thread_routine(void*) + 63
    frame #3: 0x00007fff670e1e65 libsystem_pthread.dylib`_pthread_start + 148
    frame #4: 0x00007fff670dd83b libsystem_pthread.dylib`thread_start + 15
  thread #9
    frame #0: 0x00007fff67022bce libsystem_kernel.dylib`kevent + 10
    frame #1: 0x00000001030edf07 select.cpython-37m-darwin.so`kqueue_queue_control + 903
    frame #2: 0x000000010192bff3 libpython3.7m.dylib`_PyMethodDef_RawFastCallKeywords + 259
    frame #3: 0x0000000101936885 libpython3.7m.dylib`_PyMethodDescr_FastCallKeywords + 85
    frame #4: 0x0000000101a34274 libpython3.7m.dylib`call_function + 756
    frame #5: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #6: 0x0000000101a2906c libpython3.7m.dylib`_PyEval_EvalCodeWithName + 3308
    frame #7: 0x000000010192bed6 libpython3.7m.dylib`_PyFunction_FastCallKeywords + 230
    frame #8: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #9: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #10: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #11: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #12: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #13: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #14: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #15: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #16: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #17: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #18: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #19: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #20: 0x000000010192ca84 libpython3.7m.dylib`_PyObject_Call_Prepend + 164
    frame #21: 0x000000010192e494 libpython3.7m.dylib`method_call + 36
    frame #22: 0x000000010192c496 libpython3.7m.dylib`PyObject_Call + 246
    frame #23: 0x0000000101a2b745 libpython3.7m.dylib`_PyEval_EvalFrameDefault + 8773
    frame #24: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #25: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #26: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #27: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #28: 0x0000000101a3424e libpython3.7m.dylib`call_function + 718
    frame #29: 0x0000000101a2b3bb libpython3.7m.dylib`_PyEval_EvalFrameDefault + 7867
    frame #30: 0x000000010192b94e libpython3.7m.dylib`function_code_fastcall + 254
    frame #31: 0x000000010192ca84 libpython3.7m.dylib`_PyObject_Call_Prepend + 164
    frame #32: 0x000000010192e494 libpython3.7m.dylib`method_call + 36
    frame #33: 0x000000010192c496 libpython3.7m.dylib`PyObject_Call + 246
    frame #34: 0x0000000101aeae19 libpython3.7m.dylib`t_bootstrap + 169
    frame #35: 0x0000000101a8aa57 libpython3.7m.dylib`pythread_wrapper + 39
    frame #36: 0x00007fff670e1e65 libsystem_pthread.dylib`_pthread_start + 148
    frame #37: 0x00007fff670dd83b libsystem_pthread.dylib`thread_start + 15
@michaelgale
Copy link
Author

p.s. here is the runtime trace from the above thread stack...

Process 94969 launched: '/Users/michaelgale/bin/CQ-Editor.app/Contents/MacOS/CQ-Editor' (x86_64)
My path: /Users/michaelgale/bin/CQ-Editor.app/Contents/MacOS
casroot path: /Users/michaelgale/bin/CQ-Editor.app/Contents/MacOS/oce
Warning: QApplication was created before pyqtgraph was imported; there may be problems (to avoid bugs, call QApplication.setGraphicsSystem("raster") before the QApplication is created).
2020-01-06 11:52:12.054799-0500 CQ-Editor[94969:3464644] SecTaskLoadEntitlements failed error=22 cs_flags=20, pid=94969
2020-01-06 11:52:12.054923-0500 CQ-Editor[94969:3464644] SecTaskCopyDebugDescription: CQ-Editor[94969]/0#-1 LF=0
CQ-Editor(94969,0x100e60dc0) malloc: *** error for object 0x132a9f698: pointer being freed was not allocated
CQ-Editor(94969,0x100e60dc0) malloc: *** set a breakpoint in malloc_error_break to debug
Process 94969 stopped
* thread #1, name = 'ZMQbg/1', queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff670247fa libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff670247fa <+10>: jae    0x7fff67024804            ; <+20>
    0x7fff670247fc <+12>: movq   %rax, %rdi
    0x7fff670247ff <+15>: jmp    0x7fff6701ea89            ; cerror_nocancel
    0x7fff67024804 <+20>: retq
Target 0: (CQ-Editor) stopped.

@michaelgale
Copy link
Author

p.p.s. System Info:
macOS Catalina (10.15.2)
conda version 4.8.0
binary built with pyinstaller 3.5, python 3.7.5, pyqt5 5.12.3, pythonocc-core 0.18.2
Platform: Darwin-19.2.0-x86_64-i386-64bit

@michaelgale
Copy link
Author

My hunch is that the macOS security gatekeeper tries to evaluate the app entitlements to access the file system (required by the OpenGL driver to load Shaders, etc.). This delays the initialization of the OpenGL driver enough to have the display_many method in viewer.py trigger too early and attempt to use an uninitialized OpenGL context to draw the axis lines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant
0