Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

python - Segfault in tk if plotting from an audio callback

This minimum reproducible example:

#!/usr/bin/env python3
from contextlib import contextmanager

import pyaudio
from matplotlib import pyplot as plt

RATE = 44_100


def init_plot():
    fig, ax1 = plt.subplots(ncols=1)
    broad_line, = ax1.loglog([], [])

    def plot():
        x = [0]*32
        broad_line.set_xdata(x)
        broad_line.set_ydata(x)

        print('Drawing...')

        # Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
        fig.canvas.draw()

        print('Done.')

    return plot


def audio_cb(plot):
    def cb(*args):
        try:
            plot()
            flag = pyaudio.paContinue
        except RuntimeError as e:
            print(e)
            flag = pyaudio.paComplete

        out_data = None
        return out_data, flag

    return cb


@contextmanager
def init_audio(n_frames: int, cb):
    audio = pyaudio.PyAudio()
    stream = audio.open(
        input=True,
        rate=RATE,
        channels=1,
        format=pyaudio.paFloat32,
        frames_per_buffer=n_frames,
        stream_callback=cb,
    )

    try:
        yield
    finally:
        stream.close()
        audio.terminate()

def main():
    n_frames = 32768
    plot = init_plot()
    with init_audio(n_frames, audio_cb(plot)):
        plt.show(block=True)


main()

crashes where indicated, every single time. It kills Python itself. The stacktrace from gdb is

#0  0x00007fffc3371ce5 in Tk_GetImageMasterData () from /usr/lib/libtk8.6.so
#1  0x00007fffc337d2dd in Tk_FindPhoto () from /usr/lib/libtk8.6.so
#2  0x00007fffc2909966 in mpl_tk_blit (self=<optimized out>, args=<optimized out>) at src/_tkagg.cpp:64
#3  0x000055555577020d in cfunction_call (func=0x7fffc2b30e00, args=<optimized out>, kwargs=<optimized out>)
    at Objects/methodobject.c:546
#4  0x00005555555c5d50 in _PyObject_MakeTpCall (tstate=0x7fff98023060, callable=0x7fffc2b30e00, 
    args=<optimized out>, nargs=<optimized out>, keywords=0x0) at Objects/call.c:191

...

#37 0x00007fffe2b13674 in _stream_callback_cfunction (input=0x555556beea30, output=0x0, frameCount=32768, timeInfo=<optimized out>, statusFlags=<optimized out>, userData=<optimized out>) at src/_portaudiomodule.c:1302
#38 0x00007fffdfd8cdc8 in ?? () from /usr/lib/libportaudio.so.2
#39 0x00007fffdfd8ea51 in ?? () from /usr/lib/libportaudio.so.2
#40 0x00007fffdfd9646b in ?? () from /usr/lib/libportaudio.so.2
#41 0x00007ffff7f453e9 in start_thread () from /usr/lib/libpthread.so.0
#42 0x00007ffff7d22293 in clone () from /usr/lib/libc.so.6

Should I basically give up on attempting to call into matplotlib from a PortAudio callback? If so, how best could I pass audio data from the callback to a rendering thread?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...