Navigation Menu

Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on saving figure if text.usetex is True #2635

Merged
merged 2 commits into from Aug 26, 2014

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Dec 2, 2013

The following test program crashes when matplotlib is built from master on Mac OS X 10.9 (Mountain Lion):

#!/usr/bin/env python
import matplotlib
matplotlib.rc('text', usetex=True)
from matplotlib import pyplot as plt
plt.figure()
plt.plot([0, 1], [0, 1])
plt.savefig('test.pdf')

The error message looks like this:

Python(72585,0x7fff72971310) malloc: *** error for object 0x7fa36671ba60: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

gdb reveals that the crash occurs in FreeType:

(gdb) bt
#0  0x00007fff8383a866 in __pthread_kill ()
#1  0x00007fff8734235c in pthread_kill ()
#2  0x00007fff8c206bba in abort ()
#3  0x00007fff8ca47093 in free ()
#4  0x00000001038fa296 in destroy_face ()
#5  0x00000001038fa1d0 in FT_Done_Face ()
#6  0x000000010388c1ea in std::__1::vector<FT_GlyphRec_*, std::__1::allocator<FT_GlyphRec_*> >::size () at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/vector:977
#7  0x000000010388c1ea in FT2Font::~FT2Font (this=0x1097151c0) at src/ft2font.cpp:979
#8  0x000000010388c16f in FT2Font::~FT2Font (this=0x1097151c0) at src/ft2font.cpp:974
#9  0x00000001038a4608 in Py::PythonClass<FT2Font>::extension_object_deallocator (_self=0x1097274d0) at ExtensionType.hxx:300
#10 0x00000001000334b4 in frame_dealloc ()
#11 0x00000001000a20fc in PyEval_EvalCodeEx ()

And git bisect identifies this as a regression in commit f4adec7:

f4adec7b569cfd0b30e0f8367ba8618b9e160f92 is the first bad commit
commit f4adec7b569cfd0b30e0f8367ba8618b9e160f92
Author: Michael Droettboom <mdboom@gmail.com>
Date:   Wed Aug 14 10:18:10 2013 -0400

    Use six instead of 2to3

@pwuertz
Copy link
Contributor

pwuertz commented Dec 2, 2013

I don't think that commit introduced the regression but may have exposed a problem in the handling of exceptions. I think I had a similar problem once where the Use six instead of 2to3 commit changed the string type I handed over to F2Font (python str -> python unicode), which ended in some sort of hiccup.

So, there is a problem with FT_Done_Face(face), which is called by the F2Font destructor. The face struct is created in the constructor by calling int error = FT_Open_Face(_ft2Library, &open_args, 0, &face);. So what happens if there is an error? The destructor will still try to free the face - maybe one is not supposed to do that if FT_Open_Face failed? Unfortunately the documentation doesn't seem to answer that question (http://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Open_Face).

@mdboom
Copy link
Member

mdboom commented Dec 2, 2013

@lpsinger: What platform are you on? I am unable to reproduce.

EDIT: Ok -- I see you reported the platform as Mountain Lion. Which distro and version of Python?

You may want to ensure that you did a complete rebuild by removing the build directory before re-installing.

Looking at this, I see how it's possible that FT_Done_Face(face) is being called on an uninitialized pointer, which would be very bad, and is probably causing the segfault abort before the Python exception has a chance to be thrown (and hopefully that Python exception has some clue as to the cause of the underlying problem).

@lpsinger: Do you think you could try again with the attached patch, and let us know if you get a Python traceback back instead?

Also: note to self -- this patch should be backported to 1.3.x.

@lpsinger
Copy link
Contributor Author

lpsinger commented Dec 2, 2013

@lpsinger: What platform are you on? I am unable to reproduce.

EDIT: Ok -- I see you reported the platform as Mountain Lion. Which distro and version of Python?

This is MacPorts Python.

$ python --version
Python 2.7.6

You may want to ensure that you did a complete rebuild by removing the build directory before re-installing.

Yes, I did a clean rebuild (nuked build and install directory in the bisect script).

@lpsinger: Do you think you could try again with the attached patch, and let us know if you get a Python traceback back instead?

No, still crashes; same error message.

@mdboom
Copy link
Member

mdboom commented Dec 2, 2013

Do you still get the same gdb backtrace? I'd be surprised if you did... Can you send a new one?

@lpsinger
Copy link
Contributor Author

lpsinger commented Dec 2, 2013

Do you still get the same gdb backtrace? I'd be surprised if you did... Can you send a new one?

Python(79219,0x7fff72971310) malloc: *** error for object 0x10831dfd0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Program received signal SIGABRT, Aborted.
0x00007fff8383a866 in __pthread_kill ()
(gdb) bt
#0  0x00007fff8383a866 in __pthread_kill ()
#1  0x00007fff8734235c in pthread_kill ()
#2  0x00007fff8c206bba in abort ()
#3  0x00007fff8ca47093 in free ()
#4  0x0000000104279296 in destroy_face ()
#5  0x00000001042791d0 in FT_Done_Face ()
#6  0x000000010420b6cf in std::__1::vector<FT_GlyphRec_*, std::__1::allocator<FT_GlyphRec_*> >::size () at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/vector:980
#7  0x000000010420b6cf in FT2Font::~FT2Font (this=0x10831df50) at src/ft2font.cpp:983
#8  0x000000010420b64f in FT2Font::~FT2Font (this=0x10831df50) at src/ft2font.cpp:976
#9  0x00000001042237e8 in Py::PythonClass<FT2Font>::extension_object_deallocator (_self=0x108317670) at ExtensionType.hxx:300
#10 0x00000001000334b4 in frame_dealloc ()
#11 0x00000001000a20fc in PyEval_EvalCodeEx ()
#12 0x00000001000a8f36 in fast_function ()
#13 0x00000001000a528b in PyEval_EvalFrameEx ()
#14 0x00000001000a2076 in PyEval_EvalCodeEx ()
#15 0x00000001000a8f36 in fast_function ()
#16 0x00000001000a528b in PyEval_EvalFrameEx ()
#17 0x00000001000a2076 in PyEval_EvalCodeEx ()
#18 0x00000001000a8f36 in fast_function ()
#19 0x00000001000a528b in PyEval_EvalFrameEx ()
#20 0x00000001000a2076 in PyEval_EvalCodeEx ()
#21 0x00000001000a8f36 in fast_function ()
#22 0x00000001000a528b in PyEval_EvalFrameEx ()
#23 0x00000001000a2076 in PyEval_EvalCodeEx ()
#24 0x00000001000350c6 in function_call ()
#25 0x0000000100011665 in PyObject_Call ()
#26 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#27 0x00000001000a2076 in PyEval_EvalCodeEx ()
#28 0x00000001000350c6 in function_call ()
#29 0x0000000100011665 in PyObject_Call ()
#30 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#31 0x00000001000a2076 in PyEval_EvalCodeEx ()
#32 0x00000001000350c6 in function_call ()
#33 0x0000000100011665 in PyObject_Call ()
#34 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#35 0x00000001000a2076 in PyEval_EvalCodeEx ()
#36 0x00000001000a8f36 in fast_function ()
#37 0x00000001000a528b in PyEval_EvalFrameEx ()
#38 0x00000001000a2076 in PyEval_EvalCodeEx ()
#39 0x00000001000a19a6 in PyEval_EvalCode ()
#40 0x00000001000c9611 in PyRun_FileExFlags ()
#41 0x00000001000c915e in PyRun_SimpleFileExFlags ()
#42 0x00000001000dd002 in Py_Main ()
#43 0x00007fff8d7995fd in start ()

@mdboom
Copy link
Member

mdboom commented Dec 2, 2013

Ok -- I've updated this to also not clear the glyph list out if we didn't get a good font object. Would you mind updating and rebuilding from this branch and trying again?

@lpsinger
Copy link
Contributor Author

lpsinger commented Dec 2, 2013

Ok -- I've updated this to also not clear the glyph list out if we didn't get a good font object. Would you mind updating and rebuilding from this branch and trying again?

No, still crashes:

Python(80173,0x7fff72971310) malloc: *** error for object 0x102092e10: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

Program received signal SIGABRT, Aborted.
0x00007fff8383a866 in __pthread_kill ()
(gdb) bt
#0  0x00007fff8383a866 in __pthread_kill ()
#1  0x00007fff8734235c in pthread_kill ()
#2  0x00007fff8c206bba in abort ()
#3  0x00007fff8ca47093 in free ()
#4  0x0000000103858296 in destroy_face ()
#5  0x00000001038581d0 in FT_Done_Face ()
#6  0x00000001037ea6cf in std::__1::vector<FT_GlyphRec_*, std::__1::allocator<FT_GlyphRec_*> >::size () at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1/vector:980
#7  0x00000001037ea6cf in FT2Font::~FT2Font (this=0x102092d90) at src/ft2font.cpp:982
#8  0x00000001037ea64f in FT2Font::~FT2Font (this=0x102092d90) at src/ft2font.cpp:976
#9  0x00000001038027e8 in Py::PythonClass<FT2Font>::extension_object_deallocator (_self=0x102073290) at ExtensionType.hxx:300
#10 0x00000001000334b4 in frame_dealloc ()
#11 0x00000001000a20fc in PyEval_EvalCodeEx ()
#12 0x00000001000a8f36 in fast_function ()
#13 0x00000001000a528b in PyEval_EvalFrameEx ()
#14 0x00000001000a2076 in PyEval_EvalCodeEx ()
#15 0x00000001000a8f36 in fast_function ()
#16 0x00000001000a528b in PyEval_EvalFrameEx ()
#17 0x00000001000a2076 in PyEval_EvalCodeEx ()
#18 0x00000001000a8f36 in fast_function ()
#19 0x00000001000a528b in PyEval_EvalFrameEx ()
#20 0x00000001000a2076 in PyEval_EvalCodeEx ()
#21 0x00000001000a8f36 in fast_function ()
#22 0x00000001000a528b in PyEval_EvalFrameEx ()
#23 0x00000001000a2076 in PyEval_EvalCodeEx ()
#24 0x00000001000350c6 in function_call ()
#25 0x0000000100011665 in PyObject_Call ()
#26 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#27 0x00000001000a2076 in PyEval_EvalCodeEx ()
#28 0x00000001000350c6 in function_call ()
#29 0x0000000100011665 in PyObject_Call ()
#30 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#31 0x00000001000a2076 in PyEval_EvalCodeEx ()
#32 0x00000001000350c6 in function_call ()
#33 0x0000000100011665 in PyObject_Call ()
#34 0x00000001000a64e6 in PyEval_EvalFrameEx ()
#35 0x00000001000a2076 in PyEval_EvalCodeEx ()
#36 0x00000001000a8f36 in fast_function ()
#37 0x00000001000a528b in PyEval_EvalFrameEx ()
#38 0x00000001000a2076 in PyEval_EvalCodeEx ()
#39 0x00000001000a19a6 in PyEval_EvalCode ()
#40 0x00000001000c9611 in PyRun_FileExFlags ()
#41 0x00000001000c915e in PyRun_SimpleFileExFlags ()
#42 0x00000001000dd002 in Py_Main ()
#43 0x00007fff8d7995fd in start ()

@mdboom
Copy link
Member

mdboom commented Dec 2, 2013

Ok, can you try commenting out the body of FT2Font::~FT2Font (as below)? This will leak memory, but it might allow us to get the underlying exception that's getting us in this state.

FT2Font::~FT2Font()
{
    _VERBOSE("FT2Font::~FT2Font");

/*    if (face) {
        FT_Done_Face(face);

        for (size_t i = 0; i < glyphs.size(); i++)
        {
            FT_Done_Glyph(glyphs[i]);
        }
    } */
}

@lpsinger
Copy link
Contributor Author

lpsinger commented Dec 2, 2013

Ok, can you try commenting out the body of FT2Font::~FT2Font (as below)? This will leak memory, but it might allow us to get the underlying exception that's getting us in this state.

No crash this time.

@mdboom
Copy link
Member

mdboom commented Dec 2, 2013

Not even a Python exception? Interesting.

@lpsinger
Copy link
Contributor Author

lpsinger commented Dec 2, 2013

Not even a Python exception?

No Python exception.

@pwuertz
Copy link
Contributor

pwuertz commented Dec 2, 2013

Could you perhaps add facefile and error as new class members so they can be carried over to the destructor? In the destructor they could be inspected so we know the file that causes the problem and if this is related to an FT_Open_Face error at all..

@mdboom mdboom mentioned this pull request Dec 11, 2013
@tacaswell
Copy link
Member

@mdboom What should be done about this? @lpsinger Is this still an issue in 1.4.0?

@tacaswell tacaswell added this to the v1.4.x milestone Aug 18, 2014
@mdboom
Copy link
Member

mdboom commented Aug 25, 2014

I think this PR fixes a bonafide problem, even if it doesn't fix @lpsinger's, so it should be merged (and ideally on 1.4.x if possible). We'd still need to get to the bottom of the original issue reported here, though.

tacaswell added a commit that referenced this pull request Aug 26, 2014
BUG : Don't clear glyphs if face never made
@tacaswell tacaswell merged commit 9d648fc into matplotlib:master Aug 26, 2014
@tacaswell
Copy link
Member

@mdboom Can you make a new issue for this? Merging it closed it and there is no re-open.

tacaswell added a commit that referenced this pull request Aug 26, 2014
BUG : Don't clear glyphs if face never made
@tacaswell
Copy link
Member

cherry-picked to 1.4.x as 4284599

@lpsinger
Copy link
Contributor Author

@lpsinger Is this still an issue in 1.4.0?

On master as of 9661a02, no longer crashes. Thanks!

@tacaswell
Copy link
Member

@lpsinger If it isn't a huge burden, can you also test as 1.4.0?

If it works there, then we are done, if not that gives us a very small window to figure out what changed back port it.

@QuLogic
Copy link
Member

QuLogic commented Jan 18, 2015

Unfortunately, I think this same bug (or some variant) still exists on 1.4.2. I will open a new bug shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants