Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Clean up Qt socket notifier to avoid spurious interrupt handler calls#30209

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

@chrisjbillington
Copy link
Contributor

@chrisjbillingtonchrisjbillington commentedJun 24, 2025
edited
Loading

Closes#29688

Objects without a parent are not necessarily cleaned up in PyQt when their reference count reaches zero, and must be explicitly cleaned up withdeleteLater()

This prevents the notifier firing after the signal handling was supposed to have been cleaned up, which can cause spurious errors to be printed if it runs upon further interrupts or at interpreter shutdown.

I've tested this on Linux with Python 3.13, using both of

matplotlib.use('QtAgg')matplotlib.use('Qt5Agg')

Previously, running the following withpython -i script.py:

importmatplotlib.pyplotaspltplt.plot([1,2,3], [4,5,6])plt.show()

and then pressing ctrl-C in the terminal whilst the figure was shown, would cause a traceback and error messageOSError: [Errno 9] Bad file descriptor to be printed as the interpreter exited (by e.g. subsequently pressing ctrl-D), and at least for me, cause the controlling terminal to exit for some reason.

After this change interpreter shutdown appears clean.

Similarly, as in the original bug report, runningipython and then entering in the REPL:

import matplotlib.pyplot as pltplt.plot([1, 2, 3],[5, 4, 6])plt.pause(10)

and pressing ctrl-C would result in an infinite loop ofOSError: [Errno 9] Bad file descriptor error messages, and with this change results in a singleKeyBoardInterrupt traceback as expected.

PR checklist

I've checked the docs build and the tests run - one test fails:test_font_heuristica[pdf] but it fails regardless of this change. I have only tested on Linux with Python 3.13.3.

Copy link

@github-actionsgithub-actionsbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join uson gitter for real-time discussion.

For details on testing, writing docs, and our review process, please seethe developer guide

We strive to be a welcoming and open project. Please follow ourCode of Conduct.

@chrisjbillington
Copy link
ContributorAuthor

Though I haven't seen official mention of the need to call.deleteLater(), I certainly have seen before that Python reference counts reaching zero isn't enough to clean up all state associated with QObjects in PyQt.

Here's are some mentions of this on the web:

It does seem, from runninggc.get_referrers(), that there aren't any other Python references to thisQSocketNotifier, so it does seem to be living on exclusively in the C++ layer unless explicitly deleted.

@chrisjbillington
Copy link
ContributorAuthor

Oh I see._allow_interrupt() is backend-agnostic, so Qt things don't belong there, hence the tests failing on macos. This will have to be done differently.

@chrisjbillington
Copy link
ContributorAuthor

chrisjbillington commentedJun 24, 2025
edited
Loading

Changed to put the cleanup in the backend-specific codeby connecting the event loop's aboutToQuit signal to the socket notifier's deleteLater() method edit: (that doesn't work for QEventLoop) by explicitly callingsn.deleteLater() fromhandle_sigint().

I've tested with PyQt6, PySide6, PyQt5, and PySide2. Looks like this was only ever an issue in PyQt:

            before    afterPyQt6          bad    good  PySide6       good    goodPyQt5          bad    goodPySide2       good    good

The PySide2 testing was not done in a proper dev environment, but by just editing the same file in a matplotlib 3.10.3 installation installed with pip in a Python3.10 virtual environment - seems like the setup process for a proper dev environment requires at least Python 3.11, but the last Python version supported by PySide2 was 3.10. Testing for the other bindings was done in a dev environment on Linux with Python 3.13.3.

Closesmatplotlib#29688Objects without a parent are not necessarily cleaned up in `PyQt5/6`when their reference count reaches zero, and must be explicitly cleanedup with `deleteLater()`This prevents the notifier firing after the signal handling was supposedto have been reset to its previous state.Rather than have both `bakend_bases._allow_interrupt()` and`backend_qt._allow_interrupt_qt()` hold a reference to the notifier, wepass it to  the backend-specific `handle_signint()` function forcleanup.Note the approach to cleaning up the notifier with `.deleteLater()`followed by `sendPostedEvents()` is the documented workaround for whenimmediate deletion is desired:https://doc.qt.io/qt-6/qobject.html#deleteLaterThis ensures the object is still deleted up even if the same event loopdoes not run again.
@QuLogicQuLogic added this to thev3.10.4 milestoneJun 30, 2025
@anntzer
Copy link
Contributor

Thanks for the patch!

chrisjbillington reacted with thumbs up emoji

@anntzeranntzer merged commit413ea8f intomatplotlib:mainJul 1, 2025
41 checks passed
@github-project-automationgithub-project-automationbot moved this fromNeeds review toWaiting for author inFirst Time ContributorsJul 1, 2025
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull requestJul 1, 2025
@chrisjbillingtonchrisjbillington deleted the qt-interrupt-cleanup branchJuly 1, 2025 08:20
QuLogic added a commit that referenced this pull requestJul 1, 2025
…209-on-v3.10.xBackport PR#30209 on branch v3.10.x (Clean up Qt socket notifier to avoid spurious interrupt handler calls)
@ksundenksunden mentioned this pull requestAug 7, 2025
5 tasks
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@github-actionsgithub-actions[bot]github-actions[bot] left review comments

@QuLogicQuLogicQuLogic approved these changes

@anntzeranntzeranntzer approved these changes

Assignees

No one assigned

Projects

Status: Waiting for author

Milestone

v3.10.5

Development

Successfully merging this pull request may close these issues.

[Bug]: "Bad file descriptor" raised repeatedly when plt.pause() interrupted in IPython

3 participants

@chrisjbillington@anntzer@QuLogic

[8]ページ先頭

©2009-2025 Movatter.jp