@@ -69,6 +69,17 @@ static void end_query(ares_channel_t *channel, struct server_state *server,
6969 struct query * query , ares_status_t status ,
7070 const ares_dns_record_t * dnsrec );
7171
72+
73+ static void ares__query_disassociate_from_conn (struct query * query )
74+ {
75+ /* If its not part of a connection, it can't be tracked for timeouts either */
76+ ares__slist_node_destroy (query -> node_queries_by_timeout );
77+ ares__llist_node_destroy (query -> node_queries_to_conn );
78+ query -> node_queries_by_timeout = NULL ;
79+ query -> node_queries_to_conn = NULL ;
80+ query -> conn = NULL ;
81+ }
82+
7283/* Invoke the server state callback after a success or failure */
7384static void invoke_server_state_cb (const struct server_state * server ,
7485 ares_bool_t success , int flags )
@@ -203,6 +214,8 @@ static void processfds(ares_channel_t *channel, fd_set *read_fds,
203214 /* Write last as the other 2 operations might have triggered writes */
204215 write_tcp_data (channel , write_fds , write_fd );
205216
217+ /* See if any connections should be cleaned up */
218+ ares__check_cleanup_conns (channel );
206219 ares__channel_unlock (channel );
207220}
208221
@@ -396,8 +409,6 @@ static void read_tcp_data(ares_channel_t *channel,
396409 /* Since we processed the answer, clear the tag so space can be reclaimed */
397410 ares__buf_tag_clear (server -> tcp_parser );
398411 }
399-
400- ares__check_cleanup_conn (channel , conn );
401412}
402413
403414static int socket_list_append (ares_socket_t * * socketlist , ares_socket_t fd ,
@@ -521,8 +532,6 @@ static void read_udp_packets_fd(ares_channel_t *channel,
521532 /* Try to read again only if *we* set up the socket, otherwise it may be
522533 * a blocking socket and would cause recvfrom to hang. */
523534 } while (read_len >= 0 && channel -> sock_funcs == NULL );
524-
525- ares__check_cleanup_conn (channel , conn );
526535}
527536
528537static void read_packets (ares_channel_t * channel , fd_set * read_fds ,
@@ -595,13 +604,15 @@ static void read_packets(ares_channel_t *channel, fd_set *read_fds,
595604/* If any queries have timed out, note the timeout and move them on. */
596605static void process_timeouts (ares_channel_t * channel , const ares_timeval_t * now )
597606{
598- ares__slist_node_t * node =
599- ares__slist_node_first (channel -> queries_by_timeout );
600- while (node != NULL ) {
607+ ares__slist_node_t * node ;
608+
609+ /* Just keep popping off the first as this list will re-sort as things come
610+ * and go. We don't want to try to rely on 'next' as some operation might
611+ * cause a cleanup of that pointer and would become invalid */
612+ while ((node = ares__slist_node_first (channel -> queries_by_timeout )) != NULL ) {
601613 struct query * query = ares__slist_node_val (node );
602- /* Node might be removed, cache next */
603- ares__slist_node_t * next = ares__slist_node_next (node );
604614 struct server_connection * conn ;
615+
605616 /* Since this is sorted, as soon as we hit a query that isn't timed out,
606617 * break */
607618 if (!ares__timedout (now , & query -> timeout )) {
@@ -613,9 +624,6 @@ static void process_timeouts(ares_channel_t *channel, const ares_timeval_t *now)
613624 conn = query -> conn ;
614625 server_increment_failures (conn -> server , query -> using_tcp );
615626 ares__requeue_query (query , now , ARES_ETIMEOUT );
616- ares__check_cleanup_conn (channel , conn );
617-
618- node = next ;
619627 }
620628}
621629
@@ -798,6 +806,8 @@ ares_status_t ares__requeue_query(struct query *query,
798806 ares_channel_t * channel = query -> channel ;
799807 size_t max_tries = ares__slist_len (channel -> servers ) * channel -> tries ;
800808
809+ ares__query_disassociate_from_conn (query );
810+
801811 if (status != ARES_SUCCESS ) {
802812 query -> error_status = status ;
803813 }
@@ -1030,8 +1040,6 @@ ares_status_t ares__send_query(struct query *query, const ares_timeval_t *now)
10301040 ares_status_t status ;
10311041 ares_bool_t new_connection = ARES_FALSE ;
10321042
1033- query -> conn = NULL ;
1034-
10351043 /* Choose the server to send the query to */
10361044 if (channel -> rotate ) {
10371045 /* Pull random server */
@@ -1294,12 +1302,9 @@ static ares_bool_t same_address(const struct sockaddr *sa,
12941302static void ares_detach_query (struct query * query )
12951303{
12961304 /* Remove the query from all the lists in which it is linked */
1305+ ares__query_disassociate_from_conn (query );
12971306 ares__htable_szvp_remove (query -> channel -> queries_by_qid , query -> qid );
1298- ares__slist_node_destroy (query -> node_queries_by_timeout );
1299- ares__llist_node_destroy (query -> node_queries_to_conn );
13001307 ares__llist_node_destroy (query -> node_all_queries );
1301- query -> node_queries_by_timeout = NULL ;
1302- query -> node_queries_to_conn = NULL ;
13031308 query -> node_all_queries = NULL ;
13041309}
13051310
0 commit comments