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

Segfault when calling show() after using Popen (test code inside) #6429

Closed
cmey opened this issue May 16, 2016 · 12 comments
Closed

Segfault when calling show() after using Popen (test code inside) #6429

cmey opened this issue May 16, 2016 · 12 comments

Comments

@cmey
Copy link

cmey commented May 16, 2016

Hi, please consider the following SSCCE:

import matplotlib
matplotlib.use('MacOSX')  # Segfault in backend from call to pyplot.show().
# matplotlib.use('TkAgg')  # This backend does not reproduce the segfault.
import matplotlib.pyplot as plt
import numpy as np
import signal
from subprocess import Popen, PIPE

def mplayer_view(img):
    mplayer = Popen(
        ['mplayer', '-',
         '-demuxer', 'rawvideo',
         '-rawvideo', 'w={}:h={}:format={}'.format(
            img.shape[1], img.shape[0], 'y8')],
        stdin=PIPE
    )

    tmp = img.astype('int8').tostring('C')

    # Writing twice is important to reproduce the segfault (no flush needed).
    mplayer.stdin.write(tmp)
    mplayer.stdin.write(tmp)

    mplayer.kill()

if __name__ == "__main__":
    img = np.zeros((512,512))  # Need to write enough bytes.
    mplayer_view(img)

    plt.figure()
    plt.show()  # <-- segfault here

Running that with python I get Segmentation fault: 11

Using faulthandler, the backtrace traces it to matplotlib's macosx backend from the call to show():

Fatal Python error: Segmentation fault

Current thread 0x00007fff7a0c4000 (most recent call first):
  File "/Users/cmey/.pyenv/versions/chips-3.4.3/lib/python3.4/site-packages/matplotlib/backends/backend_macosx.py", line 29 in mainloop
  File "/Users/cmey/.pyenv/versions/chips-3.4.3/lib/python3.4/site-packages/matplotlib/backend_bases.py", line 192 in __call__
  File "/Users/cmey/.pyenv/versions/chips-3.4.3/lib/python3.4/site-packages/matplotlib/pyplot.py", line 244 in show
  File "/Users/cmey/Code/python/test_matplotlib_segfault.py", line 35 in <module>
Segmentation fault: 11

I checked the return code from mplayer (with mplayer.wait()), it is -9 as it should (I kill it). If it was mplayer that segfaulted, wait() would return -11. Even if mplayer segfaults, that should not produce a segfault from matplotlib/Python.

I couldn't find another program than mplayer to pipe to, that reproduces the segfault.

Christophe
-- OSX, matplotlib version 1.5.1 from pip 8.1.2, Python 3.4.3 from pyenv, MPlayer 1.3.0-4.2.1

@tacaswell
Copy link
Member

attn @mdehoon

@rjschnei
Copy link

I also had this problem. The fix suggested above worked for me!

@cmey
Copy link
Author

cmey commented May 31, 2016

BTW, to be clear, the fix is to use another backend instead of 'MacOSX'.
To achieve this, one option is to have matplotlib.use('TkAgg') in your code (as shown above), another option is to have backend : TkAgg in your ~/.matplotlib/matplotlibrc file.

@mdehoon
Copy link
Contributor

mdehoon commented Jun 1, 2016

I think it's time to start deprecating the MacOSX backend. Maintaining the backend takes time away from the other backends.

@efiring
Copy link
Member

efiring commented Jun 1, 2016

The problem still exists on v2.x, so the switch to the Agg renderer did not fix it.

With a slight change to the SSCCE above I was able to lock up my machine completely--I had to power cycle it.

@mdboom
Copy link
Member

mdboom commented Jun 1, 2016

Things seem to work if you call mplayer.terminate() rather than mplayer.kill(). Does your use case require explicitly killing the subprocess, or are you just pointing out that if it gets killed (or mplayer itself segfaults) that matplotlib doesn't then continue along gracefully?

@cmey
Copy link
Author

cmey commented Jun 1, 2016

@mdboom My use case doesn't require killing. Yes, just replacing mplayer.kill() by mplayer.terminate() works, thank you.
But then following it by a wait() makes it segfault again, in the same place during plot().

mplayer.terminate()
mplayer.wait()

As you say, I was just pointing out a code path that leads to a segfault inside matplotlib's MacOSX backend, which I thought should never happen in any case.

@mdboom
Copy link
Member

mdboom commented Jun 1, 2016

Yeah -- ideally it shouldn't be happening, I agree. There's some interaction here that isn't cleaning up after itself.

@sschaetz
Copy link

I have the same issue on my machine, switching to matplotlib.use('TkAgg') works for me. Could we use TkAgg as default backend on mOS?

@efiring
Copy link
Member

efiring commented Sep 16, 2016

The TkAgg backend can also open a can of worms on OS X because of conflicting versions of the Tk libraries. I'm not sure whether this is completely fixed by the recent modification of backend_tkagg to use runtime loading #6442.

@matthew-brett
Copy link
Contributor

The conflicting versions really should have been solved by #6442 because matplotlib now always gets the symbols from those already loaded by Python.

efiring added a commit that referenced this issue Sep 16, 2016
efiring added a commit that referenced this issue Sep 16, 2016
@efiring
Copy link
Member

efiring commented Sep 16, 2016

I just now merged #6521 and backported it to v2.x, so I think this can be closed. Feel free to reopen if the problem is still present.

@efiring efiring closed this as completed Sep 16, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants