Bugzilla – Bug 781
Crash pressing SPACE while holding down short seek shortcut.
Last modified: 2018-08-20 11:45:53 UTC
Same occurs in 2.0.0 and 2.0.5. Does not occur in Linux. Does not seem to happen with long seek (at default settings). Mac crashed thread shows: Thread 4 Crashed: 0 net.sourceforge.audacity 0x001b09e7 RingBuffer::AvailForPut() + 7 (RingBuffer.cpp:52) 1 net.sourceforge.audacity 0x000515f7 AudioIO::FillBuffers() + 87 (AudioIO.cpp:2307) 2 net.sourceforge.audacity 0x00052118 AudioThread::Entry() + 200 (AudioIO.cpp:2232) 3 libsystem_pthread.dylib 0x9b19f5fb _pthread_body + 144 4 libsystem_pthread.dylib 0x9b19f485 _pthread_start + 130 5 libsystem_pthread.dylib 0x9b1a4cf2 thread_start + 34
I easily reproduced it and got some Windows call stacks. The immediate crash is here, in a worker thread: > Audacity.exe!RingBuffer::AvailForPut() Line 52 C++ Audacity.exe!AudioIO::GetCommonlyAvailPlayback() Line 2305 C++ Audacity.exe!AudioIO::FillBuffers() Line 2709 C++ Audacity.exe!AudioThread::Entry() Line 2235 C++ wxbase28ud_vc_custom.dll!wxThreadInternal::DoThreadStart(wxThread * thread) Line 525 C++ wxbase28ud_vc_custom.dll!wxThreadInternal::WinThreadStart(void * param) Line 552 C++ "this" RingBuffer is 0xfeeefeee. Suggesting a dangling pointer. I have seen this in my own experiments with scrubbing. My hypothesis is that two other threads, the main thread and the PortAudio callback thread, are contending to change the state that AudioThread:Entry depends on. Because of spacebar, we want to stop the playback and read AudioIO::StopStream in the main thread. But the repeating . key causes the block governed by "if (gAudioIO->mSeek)" to be reached in the PortAudio thread. It is difficult to prove that in the debugger. But I can write a fix with mutexes based on that hypothesis and see if it improves behavior.
Created attachment 517 [details] Patch to fix 781, seems to work on Windows This patch appears to fix the crash in Windows. I believe the cause of the crash was contention between the main thread and the PortAudio thread to change the state used by the Audio thread. The main thread destroyed the information, before PortAudio signalled Audio to fill its buffers once more. This resulted in dangling pointer errors in the Audio thread which were the immediate cause of crash. Fix this with a mutex to serialize the main thread and PortAudio's communications to Audio.
Paul L's fix committed at r13552.
Still fixed on Windows, Mac and Linux.
I now think my fix was not completely correct "in theory." The lines int token = gAudioIO->mStreamToken; wxMutexLocker locker(gAudioIO->mSuspendAudioThread); if (token != gAudioIO->mStreamToken) // This stream got destroyed while we waited for it return paAbort; might still allow that a seek request for one project is performed in a different project. token should instead be a value stored when AudioIO::SeekStream was called. However the timing for this theoretical bug to occur is very unlikely, and I believe the crashing behavior, resulting from one thread using data structures already deleted by another thread, is still fixed even in the presence of that bug. The fix for the crash results from the use of the mutex in this and one other place.