From: Matt Joiner Date: Mon, 11 Apr 2022 05:44:24 +0000 (+1000) Subject: Fix races around Reader and Torrent.Drop when Torrent is closed X-Git-Tag: v1.42.0 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=refs%2Ftags%2Fv1.42.0;p=btrtrc.git Fix races around Reader and Torrent.Drop when Torrent is closed --- diff --git a/client.go b/client.go index d5f96c0e..ee8261f3 100644 --- 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 } diff --git a/reader.go b/reader.go index c2f3de89..9670ff09 100644 --- 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", diff --git a/torrent.go b/torrent.go index 7e6ec24c..6a75eff3 100644 --- a/torrent.go +++ b/torrent.go @@ -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() {