loc timer util fix to handle the race condition
loc timer util stop() routine may have race condition with the timer thread, when timer expires at the same time stop() routine tries to lock mutex. The race condition can go 2 ways: * timer thread expires, unlocks mutex, context switch, stop() thread acquires lock, context switch, timer thread destroys mutex. Destroy will fail, resulting mutex leak. * timer thread expires, unlocks mutex, destroys mutex, stop() acqures lock, signal, and releases lock. Would be super rare conditions though. Fix is that we give 5 seconds for stop() thread to give up the lock when destroy. After that the timer thread will release the mutex and go on destroy. Meanwhile the stop() thread would check the lock return to move on with signal and unlock. Change-Id: Iff9e34d08a1faf0828049de2fede2e7a5d15b161 CRs-Fixed: 699856
This commit is contained in:
parent
44d7fb9ceb
commit
33e5fd9015
1 changed files with 21 additions and 5 deletions
|
@ -101,12 +101,28 @@ static void *timer_thread(void *thread_data)
|
|||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&t->timer_mutex);
|
||||
pthread_cond_destroy(&t->timer_cond);
|
||||
|
||||
if(ETIMEDOUT == ret)
|
||||
t->callback_func(t->user_data, ret);
|
||||
|
||||
// A (should be rare) race condition is that, when the loc_time_stop is called
|
||||
// and acquired mutex, we reach here. pthread_mutex_destroy will fail with
|
||||
// error code EBUSY. We give it 6 tries in 5 seconds. Should be eanough time
|
||||
// for loc_timer_stop to complete. With the 7th try, we also perform unlock
|
||||
// prior to destroy.
|
||||
{
|
||||
int i;
|
||||
for (i = 0; EBUSY == pthread_mutex_destroy(&t->timer_mutex) && i <= 5; i++) {
|
||||
if (i < 5) {
|
||||
sleep(1);
|
||||
} else {
|
||||
// nah, forget it, something is seriously wrong. Mutex has been
|
||||
// held too long. Unlock the mutext here.
|
||||
pthread_mutex_unlock(&t->timer_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_cond_destroy(&t->timer_cond);
|
||||
|
||||
free(t);
|
||||
LOC_LOGD("%s:%d]: Exit\n", __func__, __LINE__);
|
||||
return NULL;
|
||||
|
@ -175,8 +191,8 @@ _err:
|
|||
void loc_timer_stop(void* handle) {
|
||||
timer_data* t = (timer_data*)handle;
|
||||
|
||||
if (NULL != t && (READY == t->state || WAITING == t->state)) {
|
||||
pthread_mutex_lock(&(t->timer_mutex));
|
||||
if (NULL != t && (READY == t->state || WAITING == t->state) &&
|
||||
pthread_mutex_lock(&(t->timer_mutex)) == 0) {
|
||||
if (READY == t->state || WAITING == t->state) {
|
||||
pthread_cond_signal(&t->timer_cond);
|
||||
t->state = ABORT;
|
||||
|
|
Loading…
Reference in a new issue