Skip to content

Commit

Permalink
Wait for the DS thread when stopping
Browse files Browse the repository at this point in the history
The previous code would return from Pa_StopStream() when the streaming
thread signals that it is done. This is racy, because the streaming
thread is technically still running code by that point. If, for example,
the PortAudio user decides to unload the entire PortAudio DLL as soon as
Pa_StopStream() returns, hilarity could ensue.

Instead we can simply wait on the thread handle itself, which is both
safer and simpler.
  • Loading branch information
dechamps committed Jun 2, 2024
1 parent 361a3b3 commit 415558e
Showing 1 changed file with 1 addition and 27 deletions.
28 changes: 1 addition & 27 deletions src/hostapi/dsound/pa_win_ds.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,6 @@ typedef struct PaWinDsStream
#endif
HANDLE processingThread;
PA_THREAD_ID processingThreadId;
HANDLE processingThreadCompleted;
#endif

} PaWinDsStream;
Expand Down Expand Up @@ -2090,16 +2089,6 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
}
#endif

#ifndef PA_WIN_DS_USE_WMME_TIMER
stream->processingThreadCompleted = CreateEvent( NULL, /* bManualReset = */ TRUE, /* bInitialState = */ FALSE, NULL );
if( stream->processingThreadCompleted == NULL )
{
result = paUnanticipatedHostError;
PA_DS_SET_LAST_DIRECTSOUND_ERROR( GetLastError() );
goto error;
}
#endif

/* set up i/o parameters */

if( userRequestedHostInputBufferSizeFrames > 0 || userRequestedHostOutputBufferSizeFrames > 0 )
Expand Down Expand Up @@ -2292,11 +2281,6 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
CloseHandle( stream->waitableTimer );
#endif

#ifndef PA_WIN_DS_USE_WMME_TIMER
if( stream->processingThreadCompleted != NULL )
CloseHandle( stream->processingThreadCompleted );
#endif

if( stream->pDirectSoundOutputBuffer )
{
IDirectSoundBuffer_Stop( stream->pDirectSoundOutputBuffer );
Expand Down Expand Up @@ -2783,8 +2767,6 @@ PA_THREAD_FUNC ProcessingThreadProc( void *pArg )
}
#endif /* PA_WIN_DS_USE_WAITABLE_TIMER_OBJECT */

SetEvent( stream->processingThreadCompleted );

return 0;
}

Expand All @@ -2806,10 +2788,6 @@ static PaError CloseStream( PaStream* s )
CloseHandle( stream->waitableTimer );
#endif

#ifndef PA_WIN_DS_USE_WMME_TIMER
CloseHandle( stream->processingThreadCompleted );
#endif

// Cleanup the sound buffers
if( stream->pDirectSoundOutputBuffer )
{
Expand Down Expand Up @@ -2904,10 +2882,6 @@ static PaError StartStream( PaStream *s )

ResetEvent( stream->processingCompleted );

#ifndef PA_WIN_DS_USE_WMME_TIMER
ResetEvent( stream->processingThreadCompleted );
#endif

if( stream->bufferProcessor.inputChannelCount > 0 )
{
// Start the buffer capture
Expand Down Expand Up @@ -3085,7 +3059,7 @@ static PaError StopStream( PaStream *s )
#else
if( stream->processingThread )
{
if( WaitForSingleObject( stream->processingThreadCompleted, 30*100 ) == WAIT_TIMEOUT )
if( WaitForSingleObject( stream->processingThread, 30*100 ) == WAIT_TIMEOUT )
return paUnanticipatedHostError;

CloseHandle( stream->processingThread ); /* Delete thread. */
Expand Down

0 comments on commit 415558e

Please sign in to comment.