Skip to content
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

Crash in Qt / PySide2 / pyqtgraph #69

Closed
mliberty1 opened this issue Apr 3, 2020 · 9 comments
Closed

Crash in Qt / PySide2 / pyqtgraph #69

mliberty1 opened this issue Apr 3, 2020 · 9 comments
Labels
bug Something isn't working

Comments

@mliberty1
Copy link
Member

Version: 0.8.9
Platform: Win10 x64

Description
After a session with several recordings (of downsampled 200 Hz data?), started a recording. About an hour later, the Joulescope UI crashed. Here is the log file:

*****************************
* Joulescope User Interface *
* UI Version = 0.8.9        *
* Driver Version = 0.8.8    *
*****************************

info = {
  "joulescope": {
    "ui_version": "0.8.9",
    "driver_version": "0.8.8"
  },
  "platform": {
    "name": "win32",
    "python_version": "3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)]",
    "platform": "Windows-10-10.0.16299-SP0",
    "processor": "Intel64 Family 6 Model 78 Stepping 3, GenuineIntel",
    "executable": "C:\\Program Files (x86)\\Joulescope\\joulescope.exe",
    "frozen": "C:\\Program Files (x86)\\Joulescope",
...

INFO:2020-04-02 13:47:12,561:control_widget.py:52:joulescope_ui.widgets.control.control_widget:control_widget record button True
INFO:2020-04-02 13:47:15,030:data_recorder_process.py:44:joulescope_ui.data_recorder_process:DataRecorderProcess recording: C:/Users/pstim-mfg/Documents/joulescope/20200402_134712.jls
INFO:2020-04-02 13:47:16,231:data_recorder_process.py:24:joulescope_ui.data_recorder_process:DataRecorder process start
INFO:2020-04-02 13:47:16,232:data_recorder.py:86:joulescope.data_recorder:init
INFO:2020-04-02 13:48:25,949:signal.py:465:joulescope_ui.widgets.waveform.signal.current:_on_y_range_changed(current, (-0.0003795577045808324, 0.0003573472909907588))
INFO:2020-04-02 13:48:28,379:signal.py:465:joulescope_ui.widgets.waveform.signal.current:_on_y_range_changed(current, (-0.09257514863818156, 0.7478893147370147))
INFO:2020-04-02 13:48:28,412:scrollbar.py:321:joulescope_ui.widgets.waveform.scrollbar:on_regionChange(97175.24751000002, 100000.0) pixels=1162.8296668785877
INFO:2020-04-02 13:48:28,412:waveform.py:416:joulescope_ui.widgets.waveform.waveform:on_scrollbarRegionChange(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 13:48:28,416:scrollbar.py:321:joulescope_ui.widgets.waveform.scrollbar:on_regionChange(97175.24751000002, 100000.0) pixels=1162.8296668785877
INFO:2020-04-02 13:48:28,416:waveform.py:416:joulescope_ui.widgets.waveform.waveform:on_scrollbarRegionChange(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 13:48:28,417:scrollbar.py:321:joulescope_ui.widgets.waveform.scrollbar:on_regionChange(97175.24751000002, 100000.0) pixels=1162.8296668785877
INFO:2020-04-02 13:48:28,417:waveform.py:416:joulescope_ui.widgets.waveform.waveform:on_scrollbarRegionChange(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 13:48:28,440:main.py:545:joulescope_ui.main:_on_dataview_service_x_change_request(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 13:48:28,440:main.py:545:joulescope_ui.main:_on_dataview_service_x_change_request(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 13:48:28,443:main.py:545:joulescope_ui.main:_on_dataview_service_x_change_request(97175.24751000002, 100000.0, 1176)
INFO:2020-04-02 14:33:09,131:signal.py:465:joulescope_ui.widgets.waveform.signal.voltage:_on_y_range_changed(voltage, (3.769146618480714, 4.183846297626464))
Windows fatal exception: access violation

Thread 0x00011590 (most recent call first):
  File "threading.py", line 296 in wait
  File "multiprocessing\queues.py", line 224 in _feed
  File "threading.py", line 870 in run
  File "threading.py", line 926 in _bootstrap_inner
  File "threading.py", line 890 in _bootstrap

Thread 0x00010fa8 (most recent call first):
  File "site-packages\joulescope\usb\winusb\win32_device_notify.py", line 119 in _run_window
  File "threading.py", line 870 in run
  File "threading.py", line 926 in _bootstrap_inner
  File "threading.py", line 890 in _bootstrap

Thread 0x00010d00 (most recent call first):
  File "threading.py", line 300 in wait
  File "queue.py", line 179 in get
  File "site-packages\joulescope\view.py", line 157 in run
  File "threading.py", line 870 in run
  File "threading.py", line 926 in _bootstrap_inner
  File "threading.py", line 890 in _bootstrap

Thread 0x0000f168 (most recent call first):
  File "site-packages\joulescope\usb\winusb\device.py", line 821 in process
  File "site-packages\joulescope\usb\device_thread.py", line 128 in run
  File "threading.py", line 870 in run
  File "threading.py", line 926 in _bootstrap_inner
  File "threading.py", line 890 in _bootstrap

Thread 0x0000f2d8 (most recent call first):
  File "multiprocessing\connection.py", line 306 in _recv_bytes
  File "multiprocessing\connection.py", line 216 in recv_bytes
  File "multiprocessing\queues.py", line 94 in get
  File "joulescope_ui\logging_util.py", line 182 in _listener_run
  File "threading.py", line 870 in run
  File "threading.py", line 926 in _bootstrap_inner
  File "threading.py", line 890 in _bootstrap

Current thread 0x0000fd28 (most recent call first):
  File "C:\Users\PSTIM-~1\AppData\Local\Temp\embedded.x7q532nv.zip\shibokensupport\signature\errorhandler.py", line 98 in seterror_argument
  File "C:\Users\PSTIM-~1\AppData\Local\Temp\embedded.x7q532nv.zip\shibokensupport\signature\loader.py", line 101 in seterror_argument
  File "pyqtgraph\functions.py", line 1520 in arrayToQPath
  File "pyqtgraph\graphicsItems\PlotCurveItem.py", line 434 in generatePath
  File "pyqtgraph\graphicsItems\PlotCurveItem.py", line 445 in getPath
  File "pyqtgraph\graphicsItems\PlotCurveItem.py", line 463 in paint
  File "pyqtgraph\debug.py", line 91 in w
  File "pyqtgraph\widgets\GraphicsView.py", line 155 in paintEvent
  File "joulescope_ui\main.py", line 1542 in run
  File "joulescope_ui\entry_points\ui.py", line 48 in on_cmd
  File "site-packages\joulescope\entry_points\runner.py", line 75 in run
  File "joulescope_ui\__main__.py", line 41 in <module>

I investigated the pyqtgraph functions.py. The function is certainly unusual, but appears to respect the memory bounds. However, arr (the underlying numpy array) appears to go out of scope along with byteview, even though the QByteArray is returned. This could be the problem.

@mliberty1 mliberty1 added the bug Something isn't working label Apr 3, 2020
@mliberty1 mliberty1 changed the title Crash in Qt / PySide2 Crash in Qt / PySide2 / pyqtgraph Apr 3, 2020
@mliberty1
Copy link
Member Author

I spent the day investigating this issue under Win10 x64. I have found a very easy way to duplicate this crash. While in the Waveform View, continuously drag the bottom right window corner to resize the window. This causes Qt to do many redraws which seems to accelerate the crash rate. Note that the Multimeter view crashes, too. I even hacked the code to remove all pyqtgraph (all widgets but control) with no Joulescope plugged in, and observed the same crash.

After much trial and error, I am now convinced that the problem is PySide 5.14.x. I can go all the way back to Joulescope UI 0.6.10 with Python 3.8.2 and PySide 5.14.2, and I see this crash. If I then convert to Python 3.7.6 and PySide2 5.13.2, no more crashes. Going back to Joulescope & Joulescope UI dev also does not crash. However, upgrading to PySide2 5.14.2 (still Python 3.7.6) results in crashes.

Back on Python 3.8.2 and PySide, 5.14.2, I created a minimal window example

from PySide2 import QtCore, QtGui, QtWidgets
import sys

app = QtWidgets.QApplication(sys.argv)
win = QtWidgets.QMainWindow()
win.show()
app.exec_()

Dragging to resize works just fine, with no crashes. I need to figure out the gap between this minimal example and the Joulescope UI.

@mliberty1
Copy link
Member Author

I came across this presentation:
https://www.youtube.com/watch?v=ol5IuJyw-Tg

Also qtutils:
https://bitbucket.org/philipstarkey/qtutils/src/default/qtutils/invoke_in_main.py

I modified pyjoulescope_ui MainWindow to perform this resynchronization using a Python queue which then emits a Qt event, in the same way as qtutils. Still crashes.

I was also concerned that the use of numpy.float32/64 instead of Python float was causing some issues at the API level. I cleaned up both pyjoulescope and pyjoulescope_ui. I think that things may be slightly more stable, but still crashes easily on resize. Python 3.7.6 with PySide2 5.13.2 still works great.

mliberty1 added a commit that referenced this issue Apr 10, 2020
This commit applies to #71, #69, #67.

Looking at the history of Qt and PySide2, threading issues
are common defects.  To minimize the chance of encountering
these defects, this commit removes all thread synchronization
responsibility from Qt/PySide2.  The code now explicitly
performs its own resynchronization.

* Attempt to avoid any latent PYSIDE-810 and PYSIDE-813 style issues.
* Manually resynchronize all events to the Qt main thread.
* Prevent Python data from traveling across threads in Qt events.
@mliberty1
Copy link
Member Author

Release 0.8.11 reverted to PySide2 5.13.2, which appears to be much more stable. This issue is now mitigated, but not yet closed. We still need to determine the actual cause. Also see issues #67 and #71 along with these forum posts:

@mliberty1
Copy link
Member Author

I tried PySide2 5.14.2.1 (released Apr 24, 3 days ago), and the crash seems to be gone! This new version fixes two threading issues:

See the release notes.

@fusedFET
Copy link

fusedFET commented May 3, 2020

I am not sure if it is intended, but in requirements.txt, it still specifies PySide2==5.13.2 instead of PySide2==5.14.2.1.
Also, PySide2==5.14.2 requires python 3.8.1+, where the Developper section of the Readme states 3.6.

@mliberty1
Copy link
Member Author

Thanks for the comment @fusedFET. We have not yet fully tested or updated to PySide2 5.14.2.1 and Python 3.8, but we will likely make the leap in the next release. At that time, the Joulescope UI will support:

Python 3.8 with PySide2 5.14.2.1+
Python 3.6 or 3.7 with PySide 5.13

We will update requirements.txt, setup.py, and README.md (thanks!) at that time. If you are already running with Python 3.8 and PySide2 5.14.2.1, I would appreciate it if you would let me know how it's working for you!

@fusedFET
Copy link

fusedFET commented May 3, 2020

Great!
I am currently playing around, I didn't catch any issues related to PySide 5.14.2.1 with Python3.8 now.

@mliberty1
Copy link
Member Author

This issue now appears to be resolved due to the following changes:

  • PySide 5.14.2.1 with Python 3.8
  • Logging threading safety changes
  • Plugin range tool threading safety and ensuring QT event thread safety.

@mliberty1 mliberty1 moved this from To Do to Done in 2020-05 May 21, 2020
@mliberty1
Copy link
Member Author

Fixed in 0.8.16 which uses PySide 5.15.0 and Python 3.8.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
No open projects
Development

No branches or pull requests

2 participants