fix potential deadlock in View
As pointed out by magik, it is possible to deadlock if the view callback performs a blockstore operation while a Lock is pending. This fixes the issue by optimistically tracking the reference before actually calling the underlying View and limiting the scope of the lock.
This commit is contained in:
parent
c0537848b3
commit
60dd97c7fc
@ -376,19 +376,19 @@ func (s *SplitStore) HashOnRead(enabled bool) {
|
||||
}
|
||||
|
||||
func (s *SplitStore) View(cid cid.Cid, cb func([]byte) error) error {
|
||||
// optimistically protect the reference so that we can call the underlying View
|
||||
// without holding hte lock.
|
||||
// This allows the user callback to call into the blockstore without deadlocking.
|
||||
s.txnLk.RLock()
|
||||
defer s.txnLk.RUnlock()
|
||||
err := s.trackTxnRef(cid)
|
||||
s.txnLk.RUnlock()
|
||||
|
||||
err := s.hot.View(cid, cb)
|
||||
if err != nil {
|
||||
log.Warnf("error tracking reference to %s: %s", cid, err)
|
||||
}
|
||||
|
||||
err = s.hot.View(cid, cb)
|
||||
switch err {
|
||||
case nil:
|
||||
err = s.trackTxnRef(cid)
|
||||
if err != nil {
|
||||
log.Warnf("error tracking reference to %s: %s", cid, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
case bstore.ErrNotFound:
|
||||
if s.debug != nil {
|
||||
s.mx.Lock()
|
||||
|
Loading…
Reference in New Issue
Block a user