]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Fix up some crashes around piece availability
authorMatt Joiner <anacrolix@gmail.com>
Thu, 20 May 2021 04:01:31 +0000 (14:01 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 7 Jun 2021 03:01:40 +0000 (13:01 +1000)
peerconn.go
torrent.go

index 976081ab614a949c773f4c742d6827315dfe5d0c..8e3f5443e464e1197b1dd096b6f89df0f0144a25 100644 (file)
@@ -396,7 +396,9 @@ func (p *Peer) close() {
        p.discardPieceInclination()
        p._pieceRequestOrder.Clear()
        p.peerImpl.onClose()
-       p.t.decPeerPieceAvailability(p)
+       if p.t != nil {
+               p.t.decPeerPieceAvailability(p)
+       }
        for _, f := range p.callbacks.PeerClosed {
                f(p)
        }
@@ -1651,19 +1653,23 @@ func (cn *Peer) peerMaxRequests() int {
        return cn.PeerMaxRequests
 }
 
-// Returns the pieces the peer has claimed to have.
+// Returns the pieces the peer could have based on their claims. If we don't know how many pieces
+// are in the torrent, it could be a very large range the peer has sent HaveAll.
 func (cn *PeerConn) PeerPieces() bitmap.Bitmap {
        cn.locker().RLock()
        defer cn.locker().RUnlock()
        return cn.newPeerPieces()
 }
 
-// Returns a new Bitmap that includes bits for all pieces the peer claims to have.
+// Returns a new Bitmap that includes bits for all pieces the peer could have based on their claims.
 func (cn *Peer) newPeerPieces() bitmap.Bitmap {
        ret := cn._peerPieces.Copy()
        if cn.peerSentHaveAll {
-
-               ret.AddRange(0, bitmap.BitRange(cn.t.numPieces()))
+               if cn.t.haveInfo() {
+                       ret.AddRange(0, bitmap.BitRange(cn.t.numPieces()))
+               } else {
+                       ret.AddRange(0, bitmap.ToEnd)
+               }
        }
        return ret
 }
index 5190b65ebeb3a9df9cec4877c9caab996df49025..e500a47d36834f9cd287aaf739da1a3d760f10ed 100644 (file)
@@ -436,16 +436,18 @@ func (t *Torrent) onSetInfo() {
                p.onGotInfo(t.info)
        })
        for i := range t.pieces {
-               t.updatePieceCompletion(pieceIndex(i))
                p := &t.pieces[i]
-               if !p.storageCompletionOk {
-                       // t.logger.Printf("piece %s completion unknown, queueing check", p)
-                       t.queuePieceCheck(pieceIndex(i))
-               }
+               // Need to add availability before updating piece completion, as that may result in conns
+               // being dropped.
                if p.availability != 0 {
                        panic(p.availability)
                }
                p.availability = int64(t.pieceAvailabilityFromPeers(i))
+               t.updatePieceCompletion(pieceIndex(i))
+               if !p.storageCompletionOk {
+                       // t.logger.Printf("piece %s completion unknown, queueing check", p)
+                       t.queuePieceCheck(pieceIndex(i))
+               }
        }
        t.cl.event.Broadcast()
        t.gotMetainfo.Set()
@@ -1374,6 +1376,9 @@ func (t *Torrent) deletePeerConn(c *PeerConn) (ret bool) {
 }
 
 func (t *Torrent) decPeerPieceAvailability(p *Peer) {
+       if !t.haveInfo() {
+               return
+       }
        p.newPeerPieces().IterTyped(func(i int) bool {
                p.t.decPieceAvailability(i)
                return true