Repository navigation
Closed
Labels
Milestone
Description
Bug summary
As in the title.
Code for reproduction
See command-line shell. The cells `In [1]:` and `In [2]:` are copy-pasted in the shell.
Python 3.11.10 | packaged by conda-forge | (main, Oct 16 2024, 01:27:36) [GCC 13.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.31.0.dev -- An enhanced Interactive Python. Type '?' for help.
In [1]: %matplotlib
...: import matplotlib
...: import matplotlib.pyplot as plt
...:
...: plt.rcParams["figure.figsize"]=(10, 7)
...: plt.rcParams["figure.dpi"]=144
...: plt.rcParams["figure.facecolor"]="white"
...:
...: plt.ion()
Using matplotlib backend: qtagg
Out[1]: <contextlib.ExitStack at 0x7eb903e4f0d0>
In [2]: plt.plot([1, 2, 3],[5, 4, 6])
...: plt.pause(10)
^C---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
Cell In[2], line 2
1 plt.plot([1, 2, 3],[5, 4, 6])
----> 2 plt.pause(10)
File ~/.../lib/python3.11/site-packages/matplotlib/pyplot.py:756, in pause(interval)
754 canvas.draw_idle()
755 show(block=False)
--> 756 canvas.start_event_loop(interval)
757 else:
758 time.sleep(interval)
File ~/.../lib/python3.11/site-packages/matplotlib/backends/backend_qt.py:451, in FigureCanvasQT.start_event_loop(self, timeout)
448 if timeout > 0:
449 _ = QtCore.QTimer.singleShot(int(timeout * 1000), event_loop.quit)
--> 451 with _allow_interrupt_qt(event_loop):
452 qt_compat._exec(event_loop)
File ~/.../lib/python3.11/contextlib.py:144, in _GeneratorContextManager.__exit__(self, typ, value, traceback)
142 if typ is None:
143 try:
--> 144 next(self.gen)
145 except StopIteration:
146 return False
File ~/.../lib/python3.11/site-packages/matplotlib/backend_bases.py:1672, in _allow_interrupt(prepare_notifier, handle_sigint)
1670 signal.signal(signal.SIGINT, old_sigint_handler)
1671 if handler_args is not None:
-> 1672 old_sigint_handler(*handler_args)
KeyboardInterrupt:
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
File ~/.../lib/python3.11/site-packages/matplotlib/backends/backend_qt.py:166, in _allow_interrupt_qt.<locals>.prepare_notifier.<locals>._may_clear_sock()
158 @sn.activated.connect
159 def _may_clear_sock():
160 # Running a Python function on socket activation gives the interpreter a
(...)
163 # the wakeup. (We need this in case set_wakeup_fd catches a signal other
164 # than SIGINT and we shall continue waiting.)
165 try:
--> 166 rsock.recv(1)
167 except BlockingIOError:
168 # This may occasionally fire too soon or more than once on Windows, so
169 # be forgiving about reading an empty socket.
170 pass
OSError: [Errno 9] Bad file descriptorActual outcome
The error is raised.
Expected outcome
No repeated OSError.
Additional information
No response
Operating system
No response
Matplotlib Version
3.9.2
Matplotlib Backend
No response
Python version
No response
Jupyter version
No response
Installation
None
Activity
mehakkhosa commentedon Mar 5, 2025
Hi, I’d be happy to take it on!
tacaswell commentedon Mar 5, 2025
I had started to look at this but did not get very far yet, here are some notes to get you started @mehakkhosa :
matplotlib/lib/matplotlib/backends/backend_qt.py
Lines 150 to 179 in 52f659f
matplotlib/lib/matplotlib/backend_bases.py
Lines 1606 to 1661 in 52f659f
Something is clearly going wrong in the cleanup where when we get SIGINT we are not fully cleaning up after ourselves. A quick fix would be to just exit early in the callback, but I think the correct fix is to sort out how to cleanly disconnect the Qt Signal.
chrisjbillington commentedon Jun 23, 2025
I'm seeing this without IPython, when exiting the python REPL after pressing ctrl-C whilst a plot was visible. This only occurs when running a script with
python -i, not when executing the matplotlib lines from the REPL itself.Here's what triggers it for me on Arch Linux, Python 3.13.3, matplotlib 3.10.3:
Test script (for me called
2060.py):Run the script with the
-iflag:When the plot appears, go back to the terminal and hit ctrl-C, that yields this traceback, no problem so far:
But then, press ctrl-D to exit the Python interactive interpreter. At that point I get this (sorry, screengrab from a poor-quality screen recording because the window vanishes soon after)
and then weirdly the terminal emulator exits, even though it should return to bash. I get this no matter which terminal emulator I use (tried gnome-terminal, gnome console, alacritty). In gnome-console the main window is still visible but there's no prompt or anything, it's non-functional.
Notably it doesn't happen if you execute the same lines from within a REPL - only when running Python on a script with
-i.Fix issue matplotlib#29688 by cleaning up after ourselves
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls
Clean up Qt socket notifier to avoid spurious interrupt handler calls