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

agg_buffer_to_array.py crashes #1437

Merged
merged 2 commits into from Nov 6, 2012

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Nov 4, 2012

On Python 2.x for Windows, using matplotlib 1.2.0 (any rc build) with the TkAgg backend, the agg_buffer_to_array.py crashes reproducibly. Python 3.x and other backends (Qt4Agg, FltkAgg, wxAgg) seem to work OK.

The faulthandler traceback is:

Fatal Python error: Segmentation fault

Current thread 0x00001078:
  File "X:\Python27\lib\site-packages\matplotlib\image.py", line 198 in _get_unsampled_image
  File "X:\Python27\lib\site-packages\matplotlib\image.py", line 580 in make_image
  File "X:\Python27\lib\site-packages\matplotlib\image.py", line 360 in draw
  File "X:\Python27\lib\site-packages\matplotlib\artist.py", line 54 in draw_wrapper
  File "X:\Python27\lib\site-packages\matplotlib\axes.py", line 2086 in draw
  File "X:\Python27\lib\site-packages\matplotlib\artist.py", line 54 in draw_wrapper
  File "X:\Python27\lib\site-packages\matplotlib\figure.py", line 999 in draw
  File "X:\Python27\lib\site-packages\matplotlib\artist.py", line 54 in draw_wrapper
  File "X:\Python27\lib\site-packages\matplotlib\backends\backend_agg.py", line 439 in draw
  File "X:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 348 in draw
  File "X:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 276 in resize
  File "X:\Python27\lib\lib-tk\Tkinter.py", line 1410 in __call__
  File "X:\Python27\lib\lib-tk\Tkinter.py", line 911 in update
  File "X:\Python27\lib\site-packages\matplotlib\backends\backend_tkagg.py", line 574 in show
  File "X:\Python27\lib\site-packages\matplotlib\backend_bases.py", line 82 in __call__
  File "X:\Python27\lib\site-packages\matplotlib\pyplot.py", line 143 in show
  File "matplotlib-1.2.0rc3\examples\pylab_examples\agg_buffer_to_array.py", line 24 in <module>

The crash happens at line 198 of image.py:

im = _image.frombyte(self._A[yslice,xslice,:], 0)

Any access to the data of self._A, such as self._A[0,0,0], triggers a crash. The shape and dtype of self._A are correct.

Changing line 15 of agg_buffer_to_array.py from

X = np.frombuffer(buf, np.uint8)

to

X = np.fromstring(buf, np.uint8)

seems to fix this crash.

@mdboom
Copy link
Member

mdboom commented Oct 30, 2012

Do you happen to know if this is Numpy version specific?

@cgohlke
Copy link
Contributor Author

cgohlke commented Oct 30, 2012

It does not seem numpy version specific. The same crash happens with numpy-1.5.1.

@mdboom
Copy link
Member

mdboom commented Oct 30, 2012

Reproduced on Linux. Looking into it now...

@mdboom
Copy link
Member

mdboom commented Oct 31, 2012

This example really will only ever work with a non-GUI backend. What's happening is that an array is created around the image buffer and then the associated window is resized, deleting that buffer and creating a new one.

There was a:

matplotlib.use('Agg')

at the top of this example that was erroneously removed by me in 31a428c.

Unless there's a good reason to make this work with GUIs, I suggest we put that line back in. Otherwise, the fromstring approach (or any other way that copies that array data) is a fine alternative, at the expense of a memory copy.

@dmcdougall
Copy link
Member

@mdboom Does adding that line back in fix the problem? If so, I'm curious as to why that's the case.

@mdboom
Copy link
Member

mdboom commented Oct 31, 2012

np.frombuffer basically says -- "create an array that points to the given memory block without copying it". If the underlying memory block is subsequently deallocated, things explode. With the Agg backend, the image buffer is not replaced in the course of events of this example (it could have been if the figure were resized). When attached to a GUI backend, the displaying of the figure causes the figure to be resized, and thus its image buffer to be reallocated.

Adding the line back in does resolve the problem. An alternative is @cgohlke's original suggestion of copying the data. I think I'm leaning toward @cgohlke's suggestion because, while less efficient, will work in more contexts and is less surprising.

@mdboom
Copy link
Member

mdboom commented Nov 4, 2012

Fix attached. Can you confirm it works, and then we'll merge.

@cgohlke
Copy link
Contributor Author

cgohlke commented Nov 4, 2012

That will only work for Python 2. Python 3 fails with TypeError: argument 1 must be read-only pinned buffer, not memoryview.
How about forcing a copy of the numpy array: X = np.frombuffer(buf, np.uint8).copy(), maybe adding a comment why the copy is necessary?

@mdboom
Copy link
Member

mdboom commented Nov 5, 2012

Thanks. I have updated this with that approach.

@dmcdougall
Copy link
Member

Looks good. Will merge tomorrow.

dmcdougall added a commit that referenced this pull request Nov 6, 2012
@dmcdougall dmcdougall merged commit 39e18ce into matplotlib:v1.2.x Nov 6, 2012
@mdboom mdboom deleted the agg_buffer_to_array_fix branch March 3, 2015 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants