mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 02:18:42 +00:00
#5891: Fix crash on session shutdown (evdns_getaddrinfo_cancel)
This commit is contained in:
@@ -451,10 +451,10 @@ static void tau_tracker_upkeep (struct tau_tracker *);
|
|||||||
static void
|
static void
|
||||||
tau_tracker_free (struct tau_tracker * t)
|
tau_tracker_free (struct tau_tracker * t)
|
||||||
{
|
{
|
||||||
|
assert (t->dns_request == NULL);
|
||||||
|
|
||||||
if (t->addr)
|
if (t->addr)
|
||||||
evutil_freeaddrinfo (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->announces, (PtrArrayForeachFunc)tau_announce_request_free);
|
||||||
tr_ptrArrayDestruct (&t->scrapes, (PtrArrayForeachFunc)tau_scrape_request_free);
|
tr_ptrArrayDestruct (&t->scrapes, (PtrArrayForeachFunc)tau_scrape_request_free);
|
||||||
tr_free (t->host);
|
tr_free (t->host);
|
||||||
@@ -500,7 +500,7 @@ tau_tracker_on_dns (int errcode, struct evutil_addrinfo *addr, void * vtracker)
|
|||||||
if (errcode)
|
if (errcode)
|
||||||
{
|
{
|
||||||
char * errmsg = tr_strdup_printf (_("DNS Lookup failed: %s"),
|
char * errmsg = tr_strdup_printf (_("DNS Lookup failed: %s"),
|
||||||
evdns_err_to_string (errcode));
|
evutil_gai_strerror (errcode));
|
||||||
dbgmsg (tracker->key, "%s", errmsg);
|
dbgmsg (tracker->key, "%s", errmsg);
|
||||||
tau_tracker_fail_all (tracker, false, false, errmsg);
|
tau_tracker_fail_all (tracker, false, false, errmsg);
|
||||||
tr_free (errmsg);
|
tr_free (errmsg);
|
||||||
@@ -654,16 +654,18 @@ static bool
|
|||||||
tau_tracker_is_idle (const struct tau_tracker * tracker)
|
tau_tracker_is_idle (const struct tau_tracker * tracker)
|
||||||
{
|
{
|
||||||
return tr_ptrArrayEmpty (&tracker->announces)
|
return tr_ptrArrayEmpty (&tracker->announces)
|
||||||
&& tr_ptrArrayEmpty (&tracker->scrapes);
|
&& tr_ptrArrayEmpty (&tracker->scrapes)
|
||||||
|
&& tracker->dns_request == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tau_tracker_upkeep (struct tau_tracker * tracker)
|
tau_tracker_upkeep (struct tau_tracker * tracker)
|
||||||
{
|
{
|
||||||
const time_t now = tr_time ();
|
const time_t now = tr_time ();
|
||||||
|
const bool closing = tracker->close_at != 0;
|
||||||
|
|
||||||
/* if the address info is too old, expire it */
|
/* 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");
|
dbgmsg (tracker->host, "Expiring old DNS result");
|
||||||
evutil_freeaddrinfo (tracker->addr);
|
evutil_freeaddrinfo (tracker->addr);
|
||||||
tracker->addr = NULL;
|
tracker->addr = NULL;
|
||||||
@@ -674,7 +676,7 @@ tau_tracker_upkeep (struct tau_tracker * tracker)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* if we don't have an address yet, try & get one now. */
|
/* 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;
|
struct evutil_addrinfo hints;
|
||||||
memset (&hints, 0, sizeof (hints));
|
memset (&hints, 0, sizeof (hints));
|
||||||
@@ -853,6 +855,8 @@ tr_tracker_udp_start_shutdown (tr_session * session)
|
|||||||
for (i=0, n=tr_ptrArraySize (&tau->trackers); i<n; ++i)
|
for (i=0, n=tr_ptrArraySize (&tau->trackers); i<n; ++i)
|
||||||
{
|
{
|
||||||
struct tau_tracker * tracker = tr_ptrArrayNth (&tau->trackers, 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;
|
tracker->close_at = now + 3;
|
||||||
tau_tracker_upkeep (tracker);
|
tau_tracker_upkeep (tracker);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1781,13 +1781,10 @@ compareTorrentByCur (const void * va, const void * vb)
|
|||||||
static void closeBlocklists (tr_session *);
|
static void closeBlocklists (tr_session *);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sessionCloseImpl (void * vsession)
|
sessionCloseImplStart (tr_session * session)
|
||||||
{
|
{
|
||||||
int i, n;
|
int i, n;
|
||||||
tr_torrent ** torrents;
|
tr_torrent ** torrents;
|
||||||
tr_session * session = vsession;
|
|
||||||
|
|
||||||
assert (tr_isSession (session));
|
|
||||||
|
|
||||||
session->isClosing = true;
|
session->isClosing = true;
|
||||||
|
|
||||||
@@ -1829,15 +1826,11 @@ sessionCloseImpl (void * vsession)
|
|||||||
|
|
||||||
tr_cacheFree (session->cache);
|
tr_cacheFree (session->cache);
|
||||||
session->cache = NULL;
|
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: */
|
/* we had to wait until UDP trackers were closed before closing these: */
|
||||||
evdns_base_free (session->evdns_base, 0);
|
evdns_base_free (session->evdns_base, 0);
|
||||||
session->evdns_base = NULL;
|
session->evdns_base = NULL;
|
||||||
@@ -1854,6 +1847,42 @@ sessionCloseImpl (void * vsession)
|
|||||||
session->isClosed = true;
|
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
|
static int
|
||||||
deadlineReached (const time_t deadline)
|
deadlineReached (const time_t deadline)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -203,6 +203,8 @@ readFromPipe (evutil_socket_t fd,
|
|||||||
{
|
{
|
||||||
dbgmsg ("pipe eof reached... removing event listener");
|
dbgmsg ("pipe eof reached... removing event listener");
|
||||||
event_free (eh->pipeEvent);
|
event_free (eh->pipeEvent);
|
||||||
|
tr_netCloseSocket (eh->fds[0]);
|
||||||
|
event_base_loopexit (eh->base, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user