static void
tau_tracker_free (struct tau_tracker * t)
{
+ assert (t->dns_request == NULL);
+
if (t->addr)
evutil_freeaddrinfo (t->addr);
- if (t->dns_request != NULL)
- evdns_getaddrinfo_cancel (t->dns_request);
tr_ptrArrayDestruct (&t->announces, (PtrArrayForeachFunc)tau_announce_request_free);
tr_ptrArrayDestruct (&t->scrapes, (PtrArrayForeachFunc)tau_scrape_request_free);
tr_free (t->host);
if (errcode)
{
char * errmsg = tr_strdup_printf (_("DNS Lookup failed: %s"),
- evdns_err_to_string (errcode));
+ evutil_gai_strerror (errcode));
dbgmsg (tracker->key, "%s", errmsg);
tau_tracker_fail_all (tracker, false, false, errmsg);
tr_free (errmsg);
tau_tracker_is_idle (const struct tau_tracker * tracker)
{
return tr_ptrArrayEmpty (&tracker->announces)
- && tr_ptrArrayEmpty (&tracker->scrapes);
+ && tr_ptrArrayEmpty (&tracker->scrapes)
+ && tracker->dns_request == NULL;
}
static void
tau_tracker_upkeep (struct tau_tracker * tracker)
{
const time_t now = tr_time ();
+ const bool closing = tracker->close_at != 0;
/* if the address info is too old, expire it */
- if (tracker->addr && (tracker->addr_expiration_time <= now)) {
+ if (tracker->addr != NULL && (closing || tracker->addr_expiration_time <= now)) {
dbgmsg (tracker->host, "Expiring old DNS result");
evutil_freeaddrinfo (tracker->addr);
tracker->addr = NULL;
return;
/* if we don't have an address yet, try & get one now. */
- if (!tracker->addr && (tracker->dns_request == NULL))
+ if (!closing && tracker->addr == NULL && tracker->dns_request == NULL)
{
struct evutil_addrinfo hints;
memset (&hints, 0, sizeof (hints));
for (i=0, n=tr_ptrArraySize (&tau->trackers); i<n; ++i)
{
struct tau_tracker * tracker = tr_ptrArrayNth (&tau->trackers, i);
+ if (tracker->dns_request != NULL)
+ evdns_getaddrinfo_cancel (tracker->dns_request);
tracker->close_at = now + 3;
tau_tracker_upkeep (tracker);
}
static void closeBlocklists (tr_session *);
static void
-sessionCloseImpl (void * vsession)
+sessionCloseImplStart (tr_session * session)
{
int i, n;
tr_torrent ** torrents;
- tr_session * session = vsession;
-
- assert (tr_isSession (session));
session->isClosing = true;
tr_cacheFree (session->cache);
session->cache = NULL;
+}
- /* gotta keep udp running long enough to send out all
- the &event=stopped UDP tracker messages */
- while (!tr_tracker_udp_is_idle (session))
- {
- tr_tracker_udp_upkeep (session);
- tr_wait_msec (100);
- }
-
+static void
+sessionCloseImplFinish (tr_session * session)
+{
/* we had to wait until UDP trackers were closed before closing these: */
evdns_base_free (session->evdns_base, 0);
session->evdns_base = NULL;
session->isClosed = true;
}
+static void
+sessionCloseImplWaitForIdleUdp (evutil_socket_t foo UNUSED,
+ short bar UNUSED,
+ void * vsession)
+{
+ tr_session * session = vsession;
+
+ assert (tr_isSession (session));
+
+ /* gotta keep udp running long enough to send out all
+ the &event=stopped UDP tracker messages */
+ if (!tr_tracker_udp_is_idle (session))
+ {
+ tr_tracker_udp_upkeep (session);
+ tr_timerAdd (session->saveTimer, 0, 100000);
+ return;
+ }
+
+ sessionCloseImplFinish (session);
+}
+
+static void
+sessionCloseImpl (void * vsession)
+{
+ tr_session * session = vsession;
+
+ assert (tr_isSession (session));
+
+ sessionCloseImplStart (session);
+
+ /* saveTimer is not used at this point, reusing for UDP shutdown wait */
+ assert (session->saveTimer == NULL);
+ session->saveTimer = evtimer_new (session->event_base, sessionCloseImplWaitForIdleUdp, session);
+ tr_timerAdd (session->saveTimer, 0, 0);
+}
+
static int
deadlineReached (const time_t deadline)
{