Skip to content

Commit 42dd71e

Browse files
committed
Attemp to fix race condition reported in #174
This is an attempt at fixing #174 I used Google Gemini's Visual Studio Code plugin to come up with this fix. The logic seems to be sound. Below is the solution note. When Cache_close() is called and determines it's time to free the Cache struct, it must wait for any active Cache_bgdl thread to finish. It does this by calling PTHREAD_MUTEX_LOCK(&cf->bgt_lock). This is a blocking call. - Scenario A (No background thread active): The bgt_lock is in its normal unlocked state. The LOCK call succeeds immediately. - Scenario B (Background thread is active): The bgt_lock is currently locked (since step 2). The LOCK call in Cache_close() will block and wait. It will only unblock and acquire the lock after the Cache_bgdl thread has finished its work and called UNLOCK (step 3). Once PTHREAD_MUTEX_LOCK returns, Cache_close() has a guarantee that the background thread is no longer running and will not access the cf struct anymore. It then immediately calls PTHREAD_MUTEX_UNLOCK(&cf->bgt_lock) to release the lock it just acquired, leaving the mutex in a clean state before the Cache struct is freed.
1 parent 4098766 commit 42dd71e

1 file changed

Lines changed: 11 additions & 0 deletions

File tree

src/cache.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,17 @@ void Cache_close(Cache *cf)
952952
return;
953953
}
954954

955+
/*
956+
* Wait for any background download to finish before closing. If we don't
957+
* wait, Cache_free() might be called, while Cache_bgdl() is still
958+
* running. This will cause a use-after-free error.
959+
*/
960+
lprintf(cache_lock_debug,
961+
"thread %x: waiting for background download to finish for %s\n",
962+
pthread_self(), cf->path);
963+
PTHREAD_MUTEX_LOCK(&cf->bgt_lock);
964+
PTHREAD_MUTEX_UNLOCK(&cf->bgt_lock);
965+
955966
if (Meta_write(cf)) {
956967
lprintf(error, "Meta_write() error.");
957968
}

0 commit comments

Comments
 (0)