client-tracker-announcer.go | 6 +++++- t.go | 6 ++++++ torrent.go | 5 +++++ diff --git a/client-tracker-announcer.go b/client-tracker-announcer.go index a36e12b7fdaa1867f9c79b0d7abe3d40df97dadc..f374740d671d3c295839e9f3e0268569f29cf581 100644 --- a/client-tracker-announcer.go +++ b/client-tracker-announcer.go @@ -380,6 +380,10 @@ if me.announceData.ContainsKey(key) { return } t := me.torrentFromShortInfohash(key.ShortInfohash) + if t == nil { + // Crude, but the torrent was already dropped. We probably called AddTrackers late. + return + } g.MakeMapIfNil(&me.torrentForAnnounceRequests) // This can be duplicated when there's multiple trackers for a short infohash. That's fine. me.torrentForAnnounceRequests[key.ShortInfohash] = weak.Make(t) @@ -630,7 +634,7 @@ func (me *regularTrackerAnnounceDispatcher) makeTorrentInput(t *Torrent) (_ g.Option[nextAnnounceTorrentInput]) { // No torrent means the client has lost interest and the dispatcher just does followup actions. // If we drop a torrent, we still end up here but with a torrent that should result in None, so // check for that. - if t == nil || !g.MapContains(me.torrentClient.torrents, t) { + if t == nil || t.isDropped() { return } return g.Some(nextAnnounceTorrentInput{ diff --git a/t.go b/t.go index ceea328ad0a409a7d3b91e27546efd50bfc28171..82dffe1436a0a7548a64bbc26ac8336437566fc0 100644 --- a/t.go +++ b/t.go @@ -6,6 +6,7 @@ "strconv" "strings" "github.com/anacrolix/chansync/events" + g "github.com/anacrolix/generics" "github.com/anacrolix/missinggo/v2/pubsub" "github.com/anacrolix/sync" @@ -303,3 +304,8 @@ ret = append(ret, &c.peer) } return ret } + +// Was dropped from the Client. +func (t *Torrent) isDropped() bool { + return !g.MapContains(t.cl.torrents, t) +} diff --git a/torrent.go b/torrent.go index f39ef04209b9aed4e91f694d0725b001eff68160..893814b9d5a3b98b1cfe847b3e77fa1d92f3cfe4 100644 --- a/torrent.go +++ b/torrent.go @@ -1917,6 +1917,11 @@ return } func (t *Torrent) addTrackers(announceList [][]string) { + if t.isDropped() { + // Can't alter dropped Torrent because it may have skipped registering announce states with + // the announce dispatcher. + return + } fullAnnounceList := &t.announceList t.announceList = appendMissingTrackerTiers(*fullAnnounceList, len(announceList)) for tierIndex, trackerURLs := range announceList {