]> Repos - portaudio/commitdiff
wasapi:
authordmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Wed, 12 May 2010 18:08:45 +0000 (18:08 +0000)
committerdmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Wed, 12 May 2010 18:08:45 +0000 (18:08 +0000)
 - fixed occasional crash-bug which may be caused by a lightweight application that starts stream, checks if stream is running and if not terminates the stream: WASAPI implementation wasn't taking such behavior into account and stream termination (with structure deallocation) could happen during a thread start causing a crash on bad pointer usage
 - fixed Pa_IsStreamActive and similar not correctly reporting stopped stream if that was stopped from within a callback function (playback/capture) by returning paComplete

src/hostapi/wasapi/pa_win_wasapi.c

index c83a973b634166c7897b7dd5386138b628a40fe4..6103c34536d890b5153be1f99f3e1dc714aa4320 100644 (file)
@@ -519,7 +519,8 @@ typedef struct PaWasapiStream
     PA_THREAD_ID dwThreadId;\r
     HANDLE hThread;\r
        HANDLE hCloseRequest;\r
-       HANDLE hThreadDone;\r
+       HANDLE hThreadStart;        //!< signalled by thread on start\r
+       HANDLE hThreadExit;         //!< signalled by thread on exit\r
        HANDLE hBlockingOpStreamRD;\r
        HANDLE hBlockingOpStreamWR;\r
 \r
@@ -1701,8 +1702,8 @@ static const int BestToWorst[FORMATTESTS] = { paFloat32, paInt24, paInt16 };
                if (answer != paFormatIsSupported)\r
                {\r
                        // If mono, then driver does not support 1 channel, we use internal workaround\r
-                       // of tiny software mixing functionality, e.g. we provide to user buffer for 1 channel\r
-                       // but then mix into 2 of device buffer\r
+                       // of tiny software mixing functionality, e.g. we provide to user buffer 1 channel\r
+                       // but then mix into 2 for device buffer\r
                        if (params->channelCount == 1)\r
                        {\r
                                WAVEFORMATEXTENSIBLE stereo = { 0 };\r
@@ -2534,7 +2535,8 @@ static PaError CloseStream( PaStream* s )
        SAFE_RELEASE(stream->outVol);\r
 \r
     SAFE_CLOSE(stream->hThread);\r
-       SAFE_CLOSE(stream->hThreadDone);\r
+       SAFE_CLOSE(stream->hThreadStart);\r
+       SAFE_CLOSE(stream->hThreadExit);\r
        SAFE_CLOSE(stream->hCloseRequest);\r
        SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
        SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
@@ -2567,8 +2569,9 @@ static PaError StartStream( PaStream *s )
        // Create thread\r
        if (!stream->bBlocking)\r
        {\r
-               // Create thread done event\r
-               stream->hThreadDone = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+               // Create thread events\r
+               stream->hThreadStart = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+               stream->hThreadExit  = CreateEvent(NULL, TRUE, FALSE, NULL);\r
 \r
                if ((stream->in.client && stream->in.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) ||\r
                        (stream->out.client && stream->out.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))\r
@@ -2581,6 +2584,10 @@ static PaError StartStream( PaStream *s )
                        if ((stream->hThread = CREATE_THREAD(ProcThreadPoll)) == NULL)\r
                           return paUnanticipatedHostError;\r
                }\r
+\r
+               // Wait for thread to start\r
+               if (WaitForSingleObject(stream->hThreadStart, 60*1000) == WAIT_TIMEOUT)\r
+                       return paUnanticipatedHostError;\r
        }\r
        else\r
        {\r
@@ -2641,7 +2648,7 @@ static void _FinishStream(PaWasapiStream *stream)
        // Issue command to thread to stop processing and wait for thread exit\r
        if (!stream->bBlocking)\r
        {\r
-               SignalObjectAndWait(stream->hCloseRequest, stream->hThreadDone, INFINITE, FALSE);\r
+               SignalObjectAndWait(stream->hCloseRequest, stream->hThreadExit, INFINITE, FALSE);\r
        }\r
        else\r
        // Blocking mode does not own thread\r
@@ -2658,7 +2665,8 @@ static void _FinishStream(PaWasapiStream *stream)
 \r
        // Close thread handles to allow restart\r
        SAFE_CLOSE(stream->hThread);\r
-       SAFE_CLOSE(stream->hThreadDone);\r
+       SAFE_CLOSE(stream->hThreadStart);\r
+       SAFE_CLOSE(stream->hThreadExit);\r
        SAFE_CLOSE(stream->hCloseRequest);\r
        SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
        SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
@@ -3332,6 +3340,10 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
        if (!event[S_INPUT] || !event[S_OUTPUT])\r
        {\r
                PRINT(("WASAPI Thread: failed creating one or two event handles\n"));\r
+\r
+               // Prevent deadlocking in Pa_StreamStart\r
+               SetEvent(stream->hThreadStart);\r
+               // Exit\r
                goto thread_end;\r
        }\r
 \r
@@ -3372,6 +3384,9 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
        // Signal: stream running\r
        stream->running = TRUE;\r
 \r
+       // Notify: thread started\r
+       SetEvent(stream->hThreadStart);\r
+\r
        // Processing Loop\r
        for (;;)\r
     {\r
@@ -3418,8 +3433,11 @@ thread_end:
        CloseHandle(event[S_INPUT]);\r
        CloseHandle(event[S_OUTPUT]);\r
 \r
-       // Notify thread is exiting\r
-       SetEvent(stream->hThreadDone);\r
+       // Notify: thread exited\r
+       SetEvent(stream->hThreadExit);\r
+\r
+       // Notify: not running\r
+       stream->running = FALSE;\r
 \r
        return 0;\r
 }\r
@@ -3482,6 +3500,9 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
        // Signal: stream running\r
        stream->running = TRUE;\r
 \r
+       // Notify: thread started\r
+       SetEvent(stream->hThreadStart);\r
+\r
        // Processing Loop\r
        while (WaitForSingleObject(stream->hCloseRequest, sleep_ms) == WAIT_TIMEOUT)\r
     {\r
@@ -3529,8 +3550,11 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
        // Process stop\r
        _OnStreamStop(stream);\r
 \r
-       // Notify thread is exiting\r
-       SetEvent(stream->hThreadDone);\r
+       // Notify: thread exited\r
+       SetEvent(stream->hThreadExit);\r
+\r
+       // Notify: not running\r
+       stream->running = FALSE;\r
 \r
        return 0;\r
 }\r