]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Fix races around Reader and Torrent.Drop when Torrent is closed v1.42.0
authorMatt Joiner <anacrolix@gmail.com>
Mon, 11 Apr 2022 05:44:24 +0000 (15:44 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 11 Apr 2022 05:44:24 +0000 (15:44 +1000)
client.go
reader.go
torrent.go

index d5f96c0ee33d7b801065902d8d7f10eedc9aecdb..ee8261f378d580b56c5fdef1c3c6222cdfabe6b6 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1352,9 +1352,6 @@ func (cl *Client) dropTorrent(infoHash metainfo.Hash, wg *sync.WaitGroup) (err e
                return
        }
        err = t.close(wg)
-       if err != nil {
-               panic(err)
-       }
        delete(cl.torrents, infoHash)
        return
 }
index c2f3de89bcdef01765b4a201ca0c984abaf536fd..9670ff094a8a2ba77f2fd56bbd503757f113fd6b 100644 (file)
--- a/reader.go
+++ b/reader.go
@@ -245,12 +245,20 @@ func (r *reader) readOnceAt(ctx context.Context, b []byte, pos int64) (n int, er
                        err = nil
                        return
                }
+               if r.t.closed.IsSet() {
+                       err = fmt.Errorf("reading from closed torrent: %w", err)
+                       return
+               }
                r.t.cl.lock()
                // I think there's a panic here caused by the Client being closed before obtaining this
                // lock. TestDropTorrentWithMmapStorageWhileHashing seems to tickle occasionally in CI.
                func() {
                        // Just add exceptions already.
                        defer r.t.cl.unlock()
+                       if r.t.closed.IsSet() {
+                               // Can't update because Torrent's piece order is removed from Client.
+                               return
+                       }
                        // TODO: Just reset pieces in the readahead window. This might help
                        // prevent thrashing with small caches and file and piece priorities.
                        r.log(log.Fstr("error reading torrent %s piece %d offset %d, %d bytes: %v",
index 7e6ec24cc2c8c76ac507e3e3adce34c3a5e14eec..6a75eff3452209df500d4bb01c8d1a4dd06d14ac 100644 (file)
@@ -153,7 +153,7 @@ type Torrent struct {
        // Torrent sources in use keyed by the source string.
        activeSources sync.Map
        sourcesLogger log.Logger
-       
+
        smartBanCache smartBanCache
 }
 
@@ -850,7 +850,10 @@ func (t *Torrent) numPiecesCompleted() (num pieceIndex) {
 }
 
 func (t *Torrent) close(wg *sync.WaitGroup) (err error) {
-       t.closed.Set()
+       if !t.closed.Set() {
+               err = errors.New("already closed")
+               return
+       }
        if t.storage != nil {
                wg.Add(1)
                go func() {