Skip to content

Commit 3ca8069

Browse files
anntzermeeseeksmachine
authored andcommitted
Backport PR matplotlib#30209: Clean up Qt socket notifier to avoid spurious interrupt handler calls
1 parent a6cc523 commit 3ca8069

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
@@ -1616,7 +1616,8 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16161616
If SIGINT was indeed caught, after exiting the on_signal() function the
16171617
interpreter reacts to the signal according to the handler function which
16181618
had been set up by a signal.signal() call; here, we arrange to call the
1619-
backend-specific *handle_sigint* function. Finally, we call the old SIGINT
1619+
backend-specific *handle_sigint* function, passing the notifier object
1620+
as returned by prepare_notifier(). Finally, we call the old SIGINT
16201621
handler with the same arguments that were given to our custom handler.
16211622
16221623
We do this only if the old handler for SIGINT was not None, which means
@@ -1626,7 +1627,7 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16261627
Parameters
16271628
----------
16281629
prepare_notifier : Callable[[socket.socket], object]
1629-
handle_sigint : Callable[[], object]
1630+
handle_sigint : Callable[[object], object]
16301631
"""
16311632

16321633
old_sigint_handler = signal.getsignal(signal.SIGINT)
@@ -1642,9 +1643,10 @@ def _allow_interrupt(prepare_notifier, handle_sigint):
16421643
notifier = prepare_notifier(rsock)
16431644

16441645
def save_args_and_handle_sigint(*args):
1645-
nonlocal handler_args
1646+
nonlocal handler_args, notifier
16461647
handler_args = args
1647-
handle_sigint()
1648+
handle_sigint(notifier)
1649+
notifier = None
16481650

16491651
signal.signal(signal.SIGINT, save_args_and_handle_sigint)
16501652
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)