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
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.
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?
@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.
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.
Activity
tacaswell commented on May 16, 2016
attn @mdehoon
rjschnei commented on May 20, 2016
I also had this problem. The fix suggested above worked for me!
cmey commented on 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 commented on 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 commented on 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 commented on 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 commented on 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().
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 commented on 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 commented on Sep 16, 2016
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 commented on 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 commented on Sep 16, 2016
The conflicting versions really should have been solved by #6442 because matplotlib now always gets the symbols from those already loaded by Python.
Merge pull request #6521 from cimarronm/issue_6429_fix
Merge pull request #6521 from cimarronm/issue_6429_fix
efiring commented on 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.