@@ -998,7 +998,7 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio
998998 mChannelCount(0 ),
999999 mFrameSize(1 ), mFormat(AUDIO_FORMAT_INVALID),
10001000 mParamStatus(NO_ERROR),
1001- mStandby(false ), mId(id), mExiting( false ),
1001+ mStandby(false ), mId(id),
10021002 mDevice(device),
10031003 mDeathRecipient(new PMDeathRecipient(this ))
10041004{
@@ -1017,17 +1017,23 @@ AudioFlinger::ThreadBase::~ThreadBase()
10171017
10181018void AudioFlinger::ThreadBase::exit ()
10191019{
1020- // keep a strong ref on ourself so that we won't get
1021- // destroyed in the middle of requestExitAndWait()
1022- sp <ThreadBase> strongMe = this ;
1023-
10241020 ALOGV (" ThreadBase::exit" );
10251021 {
1022+ // This lock prevents the following race in thread (uniprocessor for illustration):
1023+ // if (!exitPending()) {
1024+ // // context switch from here to exit()
1025+ // // exit() calls requestExit(), what exitPending() observes
1026+ // // exit() calls signal(), which is dropped since no waiters
1027+ // // context switch back from exit() to here
1028+ // mWaitWorkCV.wait(...);
1029+ // // now thread is hung
1030+ // }
10261031 AutoMutex lock (mLock );
1027- mExiting = true ;
10281032 requestExit ();
10291033 mWaitWorkCV .signal ();
10301034 }
1035+ // When Thread::requestExitAndWait is made virtual and this method is renamed to
1036+ // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
10311037 requestExitAndWait ();
10321038}
10331039
@@ -4516,7 +4522,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
45164522 ALOGV (" Signal record thread" );
45174523 mWaitWorkCV .signal ();
45184524 // do not wait for mStartStopCond if exiting
4519- if (mExiting ) {
4525+ if (exitPending () ) {
45204526 mActiveTrack .clear ();
45214527 status = INVALID_OPERATION;
45224528 goto startError;
@@ -4543,7 +4549,7 @@ void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
45434549 if (mActiveTrack != 0 && recordTrack == mActiveTrack .get ()) {
45444550 mActiveTrack ->mState = TrackBase::PAUSING;
45454551 // do not wait for mStartStopCond if exiting
4546- if (mExiting ) {
4552+ if (exitPending () ) {
45474553 return ;
45484554 }
45494555 mStartStopCond .wait (mLock );
@@ -4989,6 +4995,8 @@ status_t AudioFlinger::closeOutput(audio_io_handle_t output)
49894995 mPlaybackThreads .removeItem (output);
49904996 }
49914997 thread->exit ();
4998+ // The thread entity (active unit of execution) is no longer running here,
4999+ // but the ThreadBase container still exists.
49925000
49935001 if (thread->type () != ThreadBase::DUPLICATING) {
49945002 AudioStreamOut *out = thread->clearOutput ();
@@ -5132,6 +5140,8 @@ status_t AudioFlinger::closeInput(audio_io_handle_t input)
51325140 mRecordThreads .removeItem (input);
51335141 }
51345142 thread->exit ();
5143+ // The thread entity (active unit of execution) is no longer running here,
5144+ // but the ThreadBase container still exists.
51355145
51365146 AudioStreamIn *in = thread->clearInput ();
51375147 assert (in != NULL );
0 commit comments