Repository navigation
Don't abort on FT2Font weakref. - #9074
Merged
Merged
Conversation
1 of 6 tasks
6 tasks
QuLogic
approved these changes
Feb 3, 2018
QuLogic
left a comment
Member
There was a problem hiding this comment.
A minor comment, but this works for me.
| */ | ||
| static NPY_INLINE int mpl_PyFile_DupClose(PyObject *file, FILE *handle, mpl_off_t orig_pos) | ||
| { | ||
| PyObject *type = NULL, *value = NULL, *tb = NULL; |
Member
There was a problem hiding this comment.
These should probably get some differentiating name, like an orig_ prefix or something.
Contributor
Author
There was a problem hiding this comment.
grepping through https://github.com/python/cpython/blob/f320be77ffb73e3b9e7fc98c37b8df3975d84b40/Modules/_io/fileio.c shows that cpython tends to stash the current exception (if any) in *exc, *val, *tb (but not without a prefix). We're not shadowing anything anyways...
Member
There was a problem hiding this comment.
Sure, but those are generally around one other call, whereas this one is around almost an entire function body.
|
|
||
| static NPY_INLINE int mpl_PyFile_CloseFile(PyObject *file) | ||
| { | ||
| PyObject *type, *value, *tb; |
Currently,
import weakref, matplotlib.ft2font
weakref.ref(matplotlib.ft2font.FT2Font("/usr/share/fonts/TTF/DejaVuSans.ttf"))
aborts Py3 with
terminate called after throwing an instance of 'char const*'
Fatal Python error: Aborted
whereas on Py2 a normal `TypeError: cannot create weak reference to
'matplotlib.ft2font.FT2Font' object` is raised.
This is because the following happens:
- Py3 sets the TypeError for failure to create a weakref.
- The FT2Font object gets GC'd as nothing is referring to it (yes,
creating a weakref to a temporary is a bit silly).
- The FT2Font destructor calls close_file_callback, which calls
mpl_PyFile_DupClose, which calls PyObject_AsFileDescriptor... which,
on Py3, calls the fileno() method on the file object.
- PyObject_AsFileDescriptor fails because the originally set TypeError
has not been cleared, so mpl_PyFile_DupClose likewise fails, causing
close_file_callback to throw a C++ exception.
Instead, carefully stash and restore the current exception state, both
in mpl_PyFile_DupClose, and likewise below, in mpl_PyFile_CloseFile (the
latter is needed because otherwise PyObject_CallMethod will clear the
exception, cf comment in CPython's Objects/abstract.c:
/* PyObject_Call() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the
caller loses its exception */
Note that if an exception *actually* gets raised by mpl_PyFile_DupClose
or mpl_PyFile_CloseFile, it will overwrite the TypeError. Strictly
speaking, on Py3, it may be preferrable to chain the exceptions, but
this seems a bit overkill (mostly, I just want to avoid aborting the
whole Python process).
anntzer
force-pushed
the
ft2font-weakref
branch
from
February 6, 2018 07:52
77bff5f to
063dae8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Currently,
aborts Py3 with
whereas on Py2 a normal
TypeError: cannot create weak reference to 'matplotlib.ft2font.FT2Font' objectis raised.This is because the following happens:
creating a weakref to a temporary is a bit silly).
mpl_PyFile_DupClose, which calls PyObject_AsFileDescriptor... which,
on Py3, calls the fileno() method on the file object.
has not been cleared, so mpl_PyFile_DupClose likewise fails, causing
close_file_callback to throw a C++ exception.
Instead, carefully stash and restore the current exception state, both
in mpl_PyFile_DupClose, and likewise below, in mpl_PyFile_CloseFile (the
latter is needed because otherwise PyObject_CallMethod will clear the
exception, cf comment in CPython's Objects/abstract.c:
Note that if an exception actually gets raised by mpl_PyFile_DupClose
or mpl_PyFile_CloseFile, it will overwrite the TypeError. Strictly
speaking, on Py3, it may be preferrable to chain the exceptions, but
this seems a bit overkill (mostly, I just want to avoid aborting the
whole Python process).
PR Summary
PR Checklist