PortAudio / portaudio

PortAudio is a cross-platform, open-source C language library for real-time audio input and output.
Other
1.43k stars 296 forks source link

null ptr dereference in pa_jack.c #818

Open RJVB opened 1 year ago

RJVB commented 1 year ago

Describe the bug The JackCallback() function assumes stream->hostApi always points to something, which apparently is not guaranteed to be true.

To Reproduce I think there's something fishy with my Jack installation or the way I'm running the daemon so I cannot provide a guaranteed recipe to reproduce this issue, but here's a terminal transcript that I can currently reproduce consistently:

> lldb-8 audacity-lnx-work/destroot/opt/local/bin/audacity.bin   
(lldb) target create "audacity-lnx-work/destroot/opt/local/bin/audacity.bin"
Current executable set to 'audacity-lnx-work/destroot/opt/local/bin/audacity.bin' (x86_64).
(lldb) r
Process 22202 stopped and restarted: thread 1 received signal: SIGCHLD
Process 22202 stopped and restarted: thread 1 received signal: SIGCHLD
ALSA lib pcm_dsnoop.c:638:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:1099:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_dmix.c:1099:(snd_pcm_dmix_open) unable to open slave
Expression 'stream->playback.pcm' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4696
Expression 'stream->playback.pcm' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4696
Expression 'err != ETIMEDOUT' failed in 'src/hostapi/jack/pa_jack.c', line: 1061
Expression 'result' failed in 'src/hostapi/jack/pa_jack.c', line: 1081
Expression 'AddStream( stream )' failed in 'src/hostapi/jack/pa_jack.c', line: 1366
Process 22202 stopped
* thread #10, name = 'audacity.bin', stop reason = signal SIGSEGV: invalid address (fault address: 0x130)
    frame #0: 0x000015554be5b6a3 libpthread.so.0`__pthread_mutex_trylock(mutex=0x0000000000000120) at pthread_mutex_trylock.c:43
(lldb) bt
* thread #10, name = 'audacity.bin', stop reason = signal SIGSEGV: invalid address (fault address: 0x130)
  * frame #0: 0x000015554be5b6a3 libpthread.so.0`__pthread_mutex_trylock(mutex=0x0000000000000120) at pthread_mutex_trylock.c:43
    frame #1: 0x0000155548377bef libportaudio.so.2`JackCallback(frames=1024, userData=<unavailable>) at pa_jack.c:1577:23
    frame #2: 0x000015554128474c libjack.so.0`___lldb_unnamed_symbol128$$libjack.so.0 + 80
    frame #3: 0x0000155541284654 libjack.so.0`___lldb_unnamed_symbol125$$libjack.so.0 + 36
    frame #4: 0x0000155541282279 libjack.so.0`___lldb_unnamed_symbol49$$libjack.so.0 + 81
    frame #5: 0x00001555412a1858 libjack.so.0`___lldb_unnamed_symbol907$$libjack.so.0 + 216
    frame #6: 0x000015554be59184 libpthread.so.0`start_thread(arg=0x000015552e07f700) at pthread_create.c:312
    frame #7: 0x000015554738f03d libc.so.6`__clone at clone.S:111
(lldb) up
frame #1: 0x0000155548377bef libportaudio.so.2`JackCallback(frames=1024, userData=<unavailable>) at pa_jack.c:1577:23
   1574         if( stream->doStart )
   1575         {
   1576             /* If we can't obtain a lock, we'll try next time */
-> 1577             int err = pthread_mutex_trylock( &stream->hostApi->mtx );
   1578             if( !err )
   1579             {

Expected behavior Preferably some kind of message that Jack cannot be used, esp. if a different host is available.

Actual behavior A SIGSEGV. See the transcript above.

Desktop (please complete the following information):

RossBencina commented 1 year ago

Thanks for the nice clean clear bug report.

stream->hostApi shouldn't be NULL anywhere in a correctly initialized stream.

RJVB commented 1 year ago

I suppose not, but with the stream of errors in the output leading up to the crash I don't want to point fingers who does what wrong where. Instead it seems clear that PortAudio catches a lot of abnormal situations before letting one slip that leads to a crash. I think the AddStream error in pa_jack.c just above is probably enough indication that the stream didn't initialise correctly and so the callback shouldn't be activated (if you don't want to add a nullptr check inside the callback)?

Jack does work on the system where this report originated, btw. It just turns out to be a PITA to get to use it cleanly on a desktop system that really wants PulseAudio running too.

philburk commented 1 year ago

These errors are interesting:

These seem to be coming from PaAlsa_GetStreamOutputCard() but I cannot find any calls to that function. Audacity uses a modified version of PortAudio.

Expression 'stream->playback.pcm' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4696

The AddStream() seems to assume the callback is already running. It times out waiting for a mutex to be freed. But the abort in the callback may prevent that.

Expression 'err != ETIMEDOUT' failed in 'src/hostapi/jack/pa_jack.c', line: 1061
Expression 'result' failed in 'src/hostapi/jack/pa_jack.c', line: 1081
Expression 'AddStream( stream )' failed in 'src/hostapi/jack/pa_jack.c', line: 1366
RJVB commented 1 year ago

On Sunday May 28 2023 11:48:30 Phil Burk wrote:

Audacity uses a modified version of PortAudio.

That's not required anymore, and from my CMake output for Audacity:

-- ========== Using system version of PortAudio ==========
-- Found PortAudio: 
        PortAudio_INCLUDE_DIR: /opt/local/include
        PortAudio_LIBRARIES: /opt/local/lib/libportaudio.so

The AddStream() seems to assume the callback is already running. It times out waiting for a mutex to be freed. But the abort in the callback may prevent that.

Ah, so maybe the nullptr dereference isn't one, but the error is trying to use an already freed mutex? I assumed stream->hostApi had to be NULL because of the mutex address in

frame #0: 0x000015554be5b6a3 libpthread.so.0`__pthread_mutex_trylock(mutex=0x0000000000000120) at pthread_mutex_trylock.c:43

but I can't remember verifying that.

RossBencina commented 7 months ago

@RJVB Do you remember when this error occurs? Is it when you start playing something or when you stop playing (i.e. during stream shutdown?).

The reason I ask, is that I suspect that there is something broken with the way pa_jack.c waits for the stream to end (among other types of waiting) and it's possible this would cause the stream data structure to be invalidated while the callback was still running (i.e. if the wait ends before it is supposed to).

Related #879

RossBencina commented 7 months ago

Probable dup of #724

RJVB commented 7 months ago

@RJVB Do you remember when this error occurs?

Sadly, no, not after all these months. But judging from the terminal output I'd say it's more likely to happen during the preparations when starting playback. I am quite certain that I didn't try to use Jack so I suppose there's no stream to wait to end for in pa_jack.c .