Skip to content

Commit

Permalink
server/swap: avoid deadlock with maker redeem ack
Browse files Browse the repository at this point in the history
When deleting a match after receiving the maker's redeem ack (of the
taker's redeem), do not violate established lock ordering of
Swapper.matchMtx and matchTracker.mtx.  This deals with the matchMtx
prior to locking the matchTracker, avoiding a possible deadlock with
another goroutine locking these.
  • Loading branch information
chappjc committed Jan 11, 2023
1 parent fa65aa5 commit 9913e2a
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions server/swap/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -1456,6 +1456,15 @@ func (s *Swapper) processAck(msg *msgjson.Message, acker *messageAcker) {
// actor.
mktMatch := db.MatchID(acker.match.Match)

// If this is the maker's (optional) redeem ack sig, we can stop tracking
// the match. Do it here to avoid lock order violation (a deadlock trap).
if acker.isMaker && !acker.isAudit { // getting Sigs.MakerRedeem
log.Debugf("Deleting completed match %v", mktMatch)
s.matchMtx.Lock() // before locking matchTracker.mtx
s.deleteMatch(acker.match)
s.matchMtx.Unlock()
}

acker.match.mtx.Lock()
defer acker.match.mtx.Unlock()

Expand Down Expand Up @@ -1486,10 +1495,6 @@ func (s *Swapper) processAck(msg *msgjson.Message, acker *messageAcker) {
if acker.isMaker { // maker acknowledging the redeem req we sent regarding the taker redeem
acker.match.Sigs.MakerRedeem = ack.Sig
// We don't save that pointless sig anymore; use it as a flag.
log.Debugf("Deleting completed match %v", mktMatch)
s.matchMtx.Lock()
s.deleteMatch(acker.match)
s.matchMtx.Unlock()
} else { // taker acknowledging the redeem req we sent regarding the maker redeem
acker.match.Sigs.TakerRedeem = ack.Sig
if err = s.storage.SaveRedeemAckSigB(mktMatch, ack.Sig); err != nil {
Expand Down

0 comments on commit 9913e2a

Please sign in to comment.