From d8611ecf2dc8eff8c7f766b4c6a755fed3feac37 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Mon, 11 Apr 2022 15:44:24 +1000 Subject: [PATCH] Fix races around Reader and Torrent.Drop when Torrent is closed --- client.go | 3 --- reader.go | 8 ++++++++ torrent.go | 7 +++++-- 3 files changed, 13 insertions(+), 5 deletions(-) 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() { -- 2.44.0