quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

ares_destroy.c (5069B)


      1 /* MIT License
      2  *
      3  * Copyright (c) 1998 Massachusetts Institute of Technology
      4  * Copyright (c) 2004 Daniel Stenberg
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * SPDX-License-Identifier: MIT
     26  */
     27 
     28 #include "ares_private.h"
     29 #include "event/ares_event.h"
     30 #include <assert.h>
     31 
     32 void ares_destroy(ares_channel_t *channel)
     33 {
     34   size_t             i;
     35   ares_llist_node_t *node = NULL;
     36 
     37   if (channel == NULL) {
     38     return;
     39   }
     40 
     41   /* Mark as being shutdown */
     42   ares_channel_lock(channel);
     43   channel->sys_up = ARES_FALSE;
     44   ares_channel_unlock(channel);
     45 
     46   /* Disable configuration change monitoring.  We can't hold a lock because
     47    * some cleanup routines, such as on Windows, are synchronous operations.
     48    * What we've observed is a system config change event was triggered right
     49    * at shutdown time and it tries to take the channel lock and the destruction
     50    * waits for that event to complete before it continues so we get a channel
     51    * lock deadlock at shutdown if we hold a lock during this process. */
     52   if (channel->optmask & ARES_OPT_EVENT_THREAD) {
     53     ares_event_thread_t *e = channel->sock_state_cb_data;
     54     if (e && e->configchg) {
     55       ares_event_configchg_destroy(e->configchg);
     56       e->configchg = NULL;
     57     }
     58   }
     59 
     60   /* Wait for reinit thread to exit if there was one pending, can't be
     61    * holding a lock as the thread may take locks. */
     62   if (channel->reinit_thread != NULL) {
     63     void *rv;
     64     ares_thread_join(channel->reinit_thread, &rv);
     65     channel->reinit_thread = NULL;
     66   }
     67 
     68   /* Lock because callbacks will be triggered, and any system-generated
     69    * callbacks need to hold a channel lock. */
     70   ares_channel_lock(channel);
     71 
     72   /* Destroy all queries */
     73   node = ares_llist_node_first(channel->all_queries);
     74   while (node != NULL) {
     75     ares_llist_node_t *next  = ares_llist_node_next(node);
     76     ares_query_t      *query = ares_llist_node_claim(node);
     77 
     78     query->node_all_queries = NULL;
     79     query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL);
     80     ares_free_query(query);
     81 
     82     node = next;
     83   }
     84 
     85   ares_queue_notify_empty(channel);
     86 
     87 #ifndef NDEBUG
     88   /* Freeing the query should remove it from all the lists in which it sits,
     89    * so all query lists should be empty now.
     90    */
     91   assert(ares_llist_len(channel->all_queries) == 0);
     92   assert(ares_htable_szvp_num_keys(channel->queries_by_qid) == 0);
     93   assert(ares_slist_len(channel->queries_by_timeout) == 0);
     94 #endif
     95 
     96   ares_destroy_servers_state(channel);
     97 
     98 #ifndef NDEBUG
     99   assert(ares_htable_asvp_num_keys(channel->connnode_by_socket) == 0);
    100 #endif
    101 
    102   /* No more callbacks will be triggered after this point, unlock */
    103   ares_channel_unlock(channel);
    104 
    105   /* Shut down the event thread */
    106   if (channel->optmask & ARES_OPT_EVENT_THREAD) {
    107     ares_event_thread_destroy(channel);
    108   }
    109 
    110   if (channel->domains) {
    111     for (i = 0; i < channel->ndomains; i++) {
    112       ares_free(channel->domains[i]);
    113     }
    114     ares_free(channel->domains);
    115   }
    116 
    117   ares_llist_destroy(channel->all_queries);
    118   ares_slist_destroy(channel->queries_by_timeout);
    119   ares_htable_szvp_destroy(channel->queries_by_qid);
    120   ares_htable_asvp_destroy(channel->connnode_by_socket);
    121 
    122   ares_free(channel->sortlist);
    123   ares_free(channel->lookups);
    124   ares_free(channel->resolvconf_path);
    125   ares_free(channel->hosts_path);
    126   ares_destroy_rand_state(channel->rand_state);
    127 
    128   ares_hosts_file_destroy(channel->hf);
    129 
    130   ares_qcache_destroy(channel->qcache);
    131 
    132   ares_channel_threading_destroy(channel);
    133 
    134   ares_free(channel);
    135 }
    136 
    137 void ares_destroy_server(ares_server_t *server)
    138 {
    139   if (server == NULL) {
    140     return; /* LCOV_EXCL_LINE: DefensiveCoding */
    141   }
    142 
    143   ares_close_sockets(server);
    144   ares_llist_destroy(server->connections);
    145   ares_free(server);
    146 }
    147 
    148 void ares_destroy_servers_state(ares_channel_t *channel)
    149 {
    150   ares_slist_node_t *node;
    151 
    152   while ((node = ares_slist_node_first(channel->servers)) != NULL) {
    153     ares_server_t *server = ares_slist_node_claim(node);
    154     ares_destroy_server(server);
    155   }
    156 
    157   ares_slist_destroy(channel->servers);
    158   channel->servers = NULL;
    159 }