fixed app terminationg issues by Ctrl-C and window closing in both backends

This commit is contained in:
2026-03-04 15:06:59 +03:00
parent a4237d2d0e
commit 6724dc0abc

View File

@ -22,6 +22,7 @@
import argparse
import io
import os
import signal
import sys
import threading
import time
@ -1732,11 +1733,42 @@ def main():
)
ani = FuncAnimation(fig, update, interval=interval_ms, blit=False)
cleanup_done = False
plt.show()
# Нормальное завершение при закрытии окна
stop_event.set()
reader.join(timeout=1.0)
def _cleanup():
nonlocal cleanup_done
if cleanup_done:
return
cleanup_done = True
stop_event.set()
reader.join(timeout=1.0)
def _handle_sigint(_signum, _frame):
_cleanup()
try:
plt.close(fig)
except Exception:
pass
prev_sigint = signal.getsignal(signal.SIGINT)
try:
fig.canvas.mpl_connect("close_event", lambda _evt: _cleanup())
except Exception:
pass
try:
signal.signal(signal.SIGINT, _handle_sigint)
except Exception:
prev_sigint = None
try:
plt.show()
finally:
_cleanup()
if prev_sigint is not None:
try:
signal.signal(signal.SIGINT, prev_sigint)
except Exception:
pass
def run_pyqtgraph(args):
@ -1787,6 +1819,10 @@ def run_pyqtgraph(args):
app.setApplicationName(str(args.title))
except Exception:
pass
try:
app.setQuitOnLastWindowClosed(True)
except Exception:
pass
win = pg.GraphicsLayoutWidget(show=True, title=args.title)
win.resize(1200, 600)
@ -2279,8 +2315,26 @@ def run_pyqtgraph(args):
timer = pg.QtCore.QTimer()
timer.timeout.connect(update)
timer.start(interval_ms)
sigint_requested = threading.Event()
sigint_timer = pg.QtCore.QTimer()
sigint_timer.setInterval(50)
sigint_timer.timeout.connect(lambda: app.quit() if sigint_requested.is_set() else None)
sigint_timer.start()
cleanup_done = False
def on_quit():
nonlocal cleanup_done
if cleanup_done:
return
cleanup_done = True
try:
timer.stop()
except Exception:
pass
try:
sigint_timer.stop()
except Exception:
pass
stop_event.set()
reader.join(timeout=1.0)
if control_window is not None:
@ -2289,12 +2343,50 @@ def run_pyqtgraph(args):
except Exception:
pass
def _handle_sigint(_signum, _frame):
sigint_requested.set()
prev_sigint = signal.getsignal(signal.SIGINT)
try:
signal.signal(signal.SIGINT, _handle_sigint)
except Exception:
prev_sigint = None
orig_close_event = getattr(win, "closeEvent", None)
def _close_event(event):
try:
if callable(orig_close_event):
orig_close_event(event)
else:
event.accept()
except Exception:
try:
event.accept()
except Exception:
pass
try:
app.quit()
except Exception:
pass
try:
win.closeEvent = _close_event # type: ignore[method-assign]
except Exception:
pass
app.aboutToQuit.connect(on_quit)
win.show()
exec_fn = getattr(app, "exec_", None) or getattr(app, "exec", None)
exec_fn()
# На случай если aboutToQuit не сработал
on_quit()
try:
exec_fn()
finally:
on_quit()
if prev_sigint is not None:
try:
signal.signal(signal.SIGINT, prev_sigint)
except Exception:
pass
if __name__ == "__main__":