Attached is a better patch that avoids the non-portable (and ugly)
recursive mutex in favor of properly releasing the lock before
reacquiring it.
>From 460c14e1db1d1cab5f405f21e4a28a39c5721a36 Mon Sep 17 00:00:00 2001
From: Eric Wong <[email protected]>
Date: Sat, 20 Oct 2012 04:17:43 +0000
Subject: [PATCH] avoid mutex deadlock in stat_cache_get()
stat_cache_get() could lead to pthread_mutex_lock(&stat_cache_mutex)
being called twice in the same thread without a matching
pthread_mutex_unlock:
stat_cache_get() - locks stat_cache_mutex
file_cache_unref()
file_cache_sync_unlocked()
stat_cache_invalidate() -> locks stat_cache_mutex again
By releasing stat_cache_mutex before calling file_cache_unref(),
we can ensure stat_cache_invalidate() won't attempt to lock
a mutex the current thread already holds.
ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=691010
---
src/statcache.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/statcache.c b/src/statcache.c
index d9e801f..83e6ca1 100644
--- a/src/statcache.c
+++ b/src/statcache.c
@@ -100,16 +100,15 @@ int stat_cache_get(const char *fn, struct stat *st) {
time(NULL) <= ce->stat_info.dead) {
*st = ce->stat_info.st;
-
- if ((f = file_cache_get(fn))) {
- st->st_size = file_cache_get_size(f);
- file_cache_unref(f);
- }
-
r = 0;
}
pthread_mutex_unlock(&stat_cache_mutex);
+
+ if ((r == 0) && (f = file_cache_get(fn))) {
+ st->st_size = file_cache_get_size(f);
+ file_cache_unref(f);
+ }
return r;
}
--
1.8.0.rc3.16.g8ead1bf