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 {
|
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()
|
s.txnLk.RLock()
|
||||||
defer s.txnLk.RUnlock()
|
err := s.trackTxnRef(cid)
|
||||||
|
s.txnLk.RUnlock()
|
||||||
|
|
||||||
err := s.hot.View(cid, cb)
|
|
||||||
switch err {
|
|
||||||
case nil:
|
|
||||||
err = s.trackTxnRef(cid)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("error tracking reference to %s: %s", cid, err)
|
log.Warnf("error tracking reference to %s: %s", cid, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
err = s.hot.View(cid, cb)
|
||||||
|
switch err {
|
||||||
case bstore.ErrNotFound:
|
case bstore.ErrNotFound:
|
||||||
if s.debug != nil {
|
if s.debug != nil {
|
||||||
s.mx.Lock()
|
s.mx.Lock()
|
||||||
|
Loading…
Reference in New Issue
Block a user