e6f2d84736
Deadlock occurs when `getActivate` function opens new blobovnicza and that invokes evict in LRU cache of open blobovniczas. `getActivate` makes `activeMtx.Lock()` and then cache evict makes `activeMtx.RLock()` and deadlock happens. Fix contains two steps: - add separate mutex to open blobovniczas (1), - split single Lock outside of `updateAndGet` (2). As for the (1) `bbolt.Open()` locks when it tries to open the same file from two threads. So separate mutex will prevent that. As for the (2) `updateAndGet` function contains from two parts. At first it checks if required blobovnicza is ready and it returns it. In this case we can use the simple RLock. But then there is an option when we should open new blobovnicza and update map of active blobovniczas. In this case we call `openBlobovnicza` without activeMtx lock. Cache evict happens there and it won't cause deadlock. Then we lock activeMtx to update the map of active blobovniczas. Concurrency can happen there. However `openBlobovnicza` will not open the same blobovnicza twice, so we can make one more check if opened blobovnicza was activated while thread was locked in activeMtx. If so, then return active blobovnicza, else finish activation. Signed-off-by: Alex Vanin <alexey@nspcc.ru> |
||
---|---|---|
.. | ||
blobovnicza.go | ||
blobovnicza_test.go | ||
blobstor.go | ||
compress.go | ||
control.go | ||
delete_big.go | ||
delete_small.go | ||
exists.go | ||
fstree.go | ||
get_big.go | ||
get_range_big.go | ||
get_range_small.go | ||
get_small.go | ||
info.go | ||
iterate.go | ||
put.go | ||
util.go |