diff options
author | Johns <johns98@gmx.net> | 2014-09-23 12:36:39 +0200 |
---|---|---|
committer | Johns <johns98@gmx.net> | 2014-09-23 12:36:39 +0200 |
commit | a3c0052c4b87b44679d8264c89d085fcda721a2e (patch) | |
tree | 7796cbee9deaf9cd63eae02ba614e84e0ede2943 | |
parent | 8b7402a397bf460e25a75add8059aa2eb83709ee (diff) | |
download | vdr-plugin-softhddevice-a3c0052c4b87b44679d8264c89d085fcda721a2e.tar.gz vdr-plugin-softhddevice-a3c0052c4b87b44679d8264c89d085fcda721a2e.tar.bz2 |
Fix audio thread close race condition.
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | audio.c | 29 |
2 files changed, 24 insertions, 6 deletions
@@ -1,6 +1,7 @@ User johns Date: + Fix audio thread close race condition. Support ffmpeg new AVFrame API in the audio codec. Config for automatic AES parameters. Use GCC built-in functions for atomic operations. @@ -149,6 +149,7 @@ static int AudioBufferTime = 336; ///< audio buffer time in ms static pthread_t AudioThread; ///< audio play thread static pthread_mutex_t AudioMutex; ///< audio condition mutex static pthread_cond_t AudioStartCond; ///< condition variable +static char AudioThreadStop; ///< stop audio thread #else static const int AudioThread; ///< dummy audio thread #endif @@ -942,7 +943,6 @@ static int AlsaThread(void) return -1; } for (;;) { - pthread_testcancel(); if (AudioPaused) { return 1; } @@ -1216,7 +1216,8 @@ static int AlsaSetup(int *freq, int *channels, int passthrough) snd_pcm_t *handle; handle = AlsaPCMHandle; - // FIXME: need lock + // no lock needed, thread exit in main loop only + //Debug(3, "audio: %s [\n", __FUNCTION__); AlsaPCMHandle = NULL; // other threads should check handle snd_pcm_close(handle); if (AudioAlsaCloseOpenDelay) { @@ -1227,6 +1228,7 @@ static int AlsaSetup(int *freq, int *channels, int passthrough) return -1; } AlsaPCMHandle = handle; + //Debug(3, "audio: %s ]\n", __FUNCTION__); } for (;;) { @@ -1548,7 +1550,6 @@ static int OssThread(void) for (;;) { struct pollfd fds[1]; - pthread_testcancel(); if (AudioPaused) { return 1; } @@ -2050,6 +2051,12 @@ static void *AudioPlayHandlerThread(void *dummy) { Debug(3, "audio: play thread started\n"); for (;;) { + // check if we should stop the thread + if (AudioThreadStop) { + Debug(3, "audio: play thread stopped\n"); + return PTHREAD_CANCELED; + } + Debug(3, "audio: wait on start condition\n"); pthread_mutex_lock(&AudioMutex); AudioRunning = 0; @@ -2072,6 +2079,11 @@ static void *AudioPlayHandlerThread(void *dummy) int err; int i; + // check if we should stop the thread + if (AudioThreadStop) { + Debug(3, "audio: play thread stopped\n"); + return PTHREAD_CANCELED; + } // look if there is a flush command in the queue flush = 0; filled = atomic_read(&AudioRingFilled); @@ -2156,6 +2168,7 @@ static void *AudioPlayHandlerThread(void *dummy) */ static void AudioInitThread(void) { + AudioThreadStop = 0; pthread_mutex_init(&AudioMutex, NULL); pthread_cond_init(&AudioStartCond, NULL); pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL); @@ -2169,10 +2182,12 @@ static void AudioExitThread(void) { void *retval; + Debug(3, "audio: %s\n", __FUNCTION__); + if (AudioThread) { - if (pthread_cancel(AudioThread)) { - Error(_("audio: can't queue cancel play thread\n")); - } + AudioThreadStop = 1; + AudioRunning = 1; // wakeup thread, if needed + pthread_cond_signal(&AudioStartCond); if (pthread_join(AudioThread, &retval) || retval != PTHREAD_CANCELED) { Error(_("audio: can't cancel play thread\n")); } @@ -2994,6 +3009,8 @@ void AudioExit(void) { const AudioModule *module; + Debug(3, "audio: %s\n", __FUNCTION__); + #ifdef USE_AUDIO_THREAD if (AudioUsedModule->Thread) { // supports threads AudioExitThread(); |