Skip to content

Commit 413ea8f

Browse files
authored
Merge pull request #30209 from chrisjbillington/qt-interrupt-cleanup
Clean up Qt socket notifier to avoid spurious interrupt handler calls
2 parents c805967 + b06d1f4 commit 413ea8f

File tree

3 files changed

+16
-9
lines changed

3 files changed

+16
-9
lines changed

lib/matplotlib/backend_bases.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,8 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16191619
If SIGINT was indeed caught, after exiting the on_signal() function the
16201620
interpreter reacts to the signal according to the handler function which
16211621
had been set up by a signal.signal() call; here, we arrange to call the
1622-
backend-specific *handle_sigint* function. Finally, we call the old SIGINT
1622+
backend-specific *handle_sigint* function, passing the notifier object
1623+
as returned by prepare_notifier(). Finally, we call the old SIGINT
16231624
handler with the same arguments that were given to our custom handler.
16241625
16251626
We do this only if the old handler for SIGINT was not None, which means
@@ -1629,7 +1630,7 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16291630
Parameters
16301631
----------
16311632
prepare_notifier : Callable[[socket.socket], object]
1632-
handle_sigint : Callable[[], object]
1633+
handle_sigint : Callable[[object], object]
16331634
"""
16341635

16351636
old_sigint_handler = signal.getsignal(signal.SIGINT)
@@ -1645,9 +1646,10 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16451646
notifier = prepare_notifier(rsock)
16461647

16471648
def save_args_and_handle_sigint(*args):
1648-
nonlocal handler_args
1649+
nonlocal handler_args, notifier
16491650
handler_args = args
1650-
handle_sigint()
1651+
handle_sigint(notifier)
1652+
notifier = None
16511653

16521654
signal.signal(signal.SIGINT, save_args_and_handle_sigint)
16531655
try:

lib/matplotlib/backends/backend_qt.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,14 @@ def _may_clear_sock():
169169
# be forgiving about reading an empty socket.
170170
pass
171171

172-
return sn # Actually keep the notifier alive.
173-
174-
def handle_sigint():
172+
# We return the QSocketNotifier so that the caller holds a reference, and we
173+
# also explicitly clean it up in handle_sigint(). Without doing both, deletion
174+
# of the socket notifier can happen prematurely or not at all.
175+
return sn
176+
177+
def handle_sigint(sn):
178+
sn.deleteLater()
179+
QtCore.QCoreApplication.sendPostedEvents(sn, QtCore.QEvent.Type.DeferredDelete)
175180
if hasattr(qapp_or_eventloop, 'closeAllWindows'):
176181
qapp_or_eventloop.closeAllWindows()
177182
qapp_or_eventloop.quit()

src/_macosx.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static void lazy_init(void) {
258258
}
259259

260260
static PyObject*
261-
stop(PyObject* self)
261+
stop(PyObject* self, PyObject* _ /* ignored */)
262262
{
263263
stopWithEvent();
264264
Py_RETURN_NONE;
@@ -1863,7 +1863,7 @@ - (void)flagsChanged:(NSEvent *)event
18631863
"written on the file descriptor given as argument.")},
18641864
{"stop",
18651865
(PyCFunction)stop,
1866-
METH_NOARGS,
1866+
METH_VARARGS,
18671867
PyDoc_STR("Stop the NSApp.")},
18681868
{"show",
18691869
(PyCFunction)show,

0 commit comments

Comments
 (0)