From cc8cbcaf9d51d104b110dbf786f8ffc1d57590b2 Mon Sep 17 00:00:00 2001 From: Steven Siloti Date: Fri, 24 Jan 2020 21:38:30 -0800 Subject: [PATCH] fix infinite loop when announcing In torrent::announce_with_tracker there is a check after announcing all of a tracker's endpoints to see if all required announces have already been sent according to the tier settings. if (std::all_of(listen_socket_states.begin(), listen_socket_states.end() , [](announce_state const& s) { return s.done; })) break; Commit ab07eceead added a check which can cause listen_socket_states to not be populated if all endpoints for the first tracker are disabled. This causes the early break out code above to trigger and prevent any announces from being sent. The extra check is not in torrent::update_tracker_timer though, so if it thinks there is at least one endpoint ready to announce it will immediately trigger another on_tracker_announce, again, and again. Simple fix is to move the offending check below the code which populates listen_socket_states so the the latter will execute unconditionally. --- src/torrent.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/torrent.cpp b/src/torrent.cpp index e68401824..273251a7b 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -2937,10 +2937,11 @@ bool is_downloading_state(int const st) for (auto& aep : ae.endpoints) { - // if we haven't sent an event=start to the tracker, there's no - // point in sending an event=stopped - if (!aep.enabled || (!aep.start_sent && req.event == tracker_request::stopped)) - continue; + // do not add code which continues to the next endpoint here! + // listen_socket_states needs to be populated even if none of the endpoints + // will be announcing for this tracker + // otherwise the early bail out when neither announce_to_all_trackers + // nor announce_to_all_tiers is set may be triggered prematurely auto aep_state_iter = std::find_if(listen_socket_states.begin(), listen_socket_states.end() , [&](announce_state const& s) { return s.socket == aep.socket; }); @@ -2953,6 +2954,11 @@ bool is_downloading_state(int const st) if (state.done) continue; + // if we haven't sent an event=start to the tracker, there's no + // point in sending an event=stopped + if (!aep.enabled || (!aep.start_sent && req.event == tracker_request::stopped)) + continue; + #ifndef TORRENT_DISABLE_LOGGING if (should_log()) {