From: KimJeongYeon Date: Mon, 14 Nov 2016 08:54:56 +0000 (+0900) Subject: audio-io fixed crash at audio_in_read() of another thread. X-Git-Tag: accepted/tizen/common/20161115.200735^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F78%2F97478%2F3;p=platform%2Fcore%2Fapi%2Faudio-io.git audio-io fixed crash at audio_in_read() of another thread. There are no syncronization between audio_in_read() and audio_in_unprepare(). Therefore, assert crash occurs possibly while use multiple reader thread. Changes: * Add locking method at audio_in_read() and null check of mpPulseAudioClient. * Fixed syncronous-method of audio_out_write() too. * Miscellaneous typos are fixed. [Version] 0.3.45 [Profile] Common [Issue Type] Bug Fix Signed-off-by: KimJeongYeon Change-Id: I18147b9e1e7bb5c16816250d65d2ff066f6383b7 --- diff --git a/packaging/capi-media-audio-io.spec b/packaging/capi-media-audio-io.spec index 30ee55e..7c36bf2 100644 --- a/packaging/capi-media-audio-io.spec +++ b/packaging/capi-media-audio-io.spec @@ -1,6 +1,6 @@ Name: capi-media-audio-io Summary: An Audio Input & Audio Output library in Tizen Native API -Version: 0.3.44 +Version: 0.3.45 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/cpp/CAudioInput.cpp b/src/cpp/CAudioInput.cpp index c806f9f..919cecd 100644 --- a/src/cpp/CAudioInput.cpp +++ b/src/cpp/CAudioInput.cpp @@ -250,7 +250,7 @@ void CAudioInput::prepare() throw(CAudioError) { THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [type:%d]", static_cast(audioType)); } - if (mpAudioSessionHandler->getId() < 0) { //Did not registerSound() + if (mpAudioSessionHandler->getId() < 0) { // Did not registerSound() // Check session to skip registration if (isForceIgnore() == false && mpAudioSessionHandler->isSkipSessionEvent() == false) { // Register ASM Listener @@ -446,9 +446,18 @@ size_t CAudioInput::read(void* buffer, size_t length) throw(CAudioError) { int ret = 0; try { + internalLock(); + + // If another thread did call unprepare, do not read + if (mpPulseAudioClient == NULL) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient"); + // Block until read done ret = mpPulseAudioClient->read(buffer, length); + + internalUnlock(); } catch (CAudioError e) { + internalUnlock(); throw e; } diff --git a/src/cpp/CAudioOutput.cpp b/src/cpp/CAudioOutput.cpp index 2f70ed6..267ba95 100644 --- a/src/cpp/CAudioOutput.cpp +++ b/src/cpp/CAudioOutput.cpp @@ -150,7 +150,7 @@ void CAudioOutput::prepare() throw(CAudioError) { THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "The audioType is invalid [type:%d]", static_cast(audioType)); } - if (mpAudioSessionHandler->getId() < 0) { //Did not registerSound() + if (mpAudioSessionHandler->getId() < 0) { // Did not registerSound() if (isForceIgnore() == false) { // Register ASM Listener AUDIO_IO_LOGD("Register ASM Listener"); @@ -327,7 +327,7 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_ARGUMENT, "Parameters are invalid - buffer:%p, length:%zu", buffer, length); } - /* When write() is called in PulseAudio callback, bypass a pcm data to PulseAudioClient (For Asynchronous) */ + /* When write() is called in PulseAudio callback, bypass a pcm data to CPulseAudioClient (For Asynchronous) */ if (mpPulseAudioClient->isInThread() == true) { int ret = mpPulseAudioClient->write(buffer, length); if (ret < 0) { @@ -340,6 +340,10 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) /* For synchronization */ internalLock(); + // If another thread did call unprepare, do not write + if (mpPulseAudioClient == NULL) + THROW_ERROR_MSG(CAudioError::EError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient"); + // Sets synchronous flag __mIsUsedSyncWrite = true; @@ -360,7 +364,7 @@ size_t CAudioOutput::write(const void* buffer, size_t length) throw(CAudioError) } #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("PulseAudioClient->write(buffer:%p, length:%d)", buffer, l); + AUDIO_IO_LOGD("CPulseAudioClient->write(buffer:%p, length:%d)", buffer, l); #endif int ret = mpPulseAudioClient->write(buffer, l); diff --git a/src/cpp/CPulseAudioClient.cpp b/src/cpp/CPulseAudioClient.cpp index 74cd735..bfe72b2 100644 --- a/src/cpp/CPulseAudioClient.cpp +++ b/src/cpp/CPulseAudioClient.cpp @@ -455,7 +455,7 @@ int CPulseAudioClient::read(void* buffer, size_t length) throw(CAudioError) { // Copy partial pcm data on out parameter #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("memcpy() that a peeked buffer[%], index[%d], length[%d] on out buffer", (const uint8_t*)(__mpSyncReadDataPtr) + __mSyncReadIndex, __mSyncReadIndex, l); + AUDIO_IO_LOGD("memcpy() that a peeked buffer[0x%x], index[%d], length[%d] on out buffer", (const uint8_t*)(__mpSyncReadDataPtr) + __mSyncReadIndex, __mSyncReadIndex, l); #endif memcpy(buffer, (const uint8_t*)__mpSyncReadDataPtr + __mSyncReadIndex, l); diff --git a/src/cpp/cpp_audio_io.cpp b/src/cpp/cpp_audio_io.cpp index 55d1f7b..10ffe8a 100644 --- a/src/cpp/cpp_audio_io.cpp +++ b/src/cpp/cpp_audio_io.cpp @@ -1284,10 +1284,10 @@ int cpp_audio_out_write(audio_out_h output, void *buffer, unsigned int length) { if (outputHandle == NULL) { THROW_ERROR_MSG_FORMAT(CAudioError::EError::ERROR_INVALID_HANDLE, "Handle is NULL"); } - size_t writen = outputHandle->write(buffer, static_cast(length)); - ret = static_cast(writen); + size_t written = outputHandle->write(buffer, static_cast(length)); + ret = static_cast(written); #ifdef _AUDIO_IO_DEBUG_TIMING_ - AUDIO_IO_LOGD("writen:%d", writen); + AUDIO_IO_LOGD("written:%d", written); #endif } catch (CAudioError e) { AUDIO_IO_LOGE("%s", e.getErrorMsg()); diff --git a/test/audio_io_test.c b/test/audio_io_test.c index 81043ce..ca89a73 100644 --- a/test/audio_io_test.c +++ b/test/audio_io_test.c @@ -168,6 +168,7 @@ int audio_io_test(int length, int num, int ch) fclose(fp); + audio_in_unprepare(input); audio_in_destroy(input); }