From 359cef4e8caa0a468a21da26b516624161b56d6a Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Tue, 26 Jun 2018 22:55:40 +0800 Subject: [PATCH] Memory leak fix. --- etc/smartdns/smartdns.conf | 2 -- src/Makefile | 4 +-- src/conf.c | 2 +- src/dns_client.c | 31 ++++++++++++--------- src/fast_ping.c | 55 +++++++++++++++++++++++++++++--------- src/fast_ping.h | 3 ++- src/include/art.h | 2 +- src/lib/art.c | 28 +++++++++++-------- src/tlog.c | 8 +++--- 9 files changed, 89 insertions(+), 46 deletions(-) diff --git a/etc/smartdns/smartdns.conf b/etc/smartdns/smartdns.conf index b8533ea..4e02419 100644 --- a/etc/smartdns/smartdns.conf +++ b/etc/smartdns/smartdns.conf @@ -46,5 +46,3 @@ server 202.141.162.123:53 # specific address to domain # address /domain/ip # address /www.example.com/1.2.3.4 -address /cnzz.com/127.0.0.1 -address /adsame.com/127.0.0.1 \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index 2a8b166..f39cccc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,10 +1,10 @@ BIN=smartdns OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o util.o tlog.o conf.o lib/rbtree.o lib/art.o -CFLAGS=-g -O0 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing +CFLAGS=-g -O3 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing CFLAGS +=-Iinclude CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\" -CXXFLAGS=-g -O0 -Wall -std=c++11 +CXXFLAGS=-g -O3 -Wall -std=c++11 CXXFLAGS +=-Iinclude .PHONY: all diff --git a/src/conf.c b/src/conf.c index 6596956..d537dbb 100644 --- a/src/conf.c +++ b/src/conf.c @@ -71,7 +71,7 @@ void config_address_destroy(void) int config_address(char *value) { - struct dns_address *address; + struct dns_address *address = NULL; char ip[MAX_IP_LEN]; char domain_key[DNS_MAX_CONF_CNAME_LEN]; char *begin = NULL; diff --git a/src/dns_client.c b/src/dns_client.c index 980a3f6..f233de7 100644 --- a/src/dns_client.c +++ b/src/dns_client.c @@ -352,6 +352,11 @@ int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type) return _dns_client_server_operate(server_ip, port, server_type, 1); } +void _dns_client_query_get(struct dns_query_struct *query) +{ + atomic_inc(&query->refcnt); +} + void _dns_client_query_release(struct dns_query_struct *query) { int refcnt = atomic_dec_return(&query->refcnt); @@ -419,11 +424,6 @@ void _dns_client_query_remove_all(void) return; } -void _dns_client_query_get(struct dns_query_struct *query) -{ - atomic_inc(&query->refcnt); -} - void _dns_client_period_run(void) { struct dns_query_struct *query, *tmp; @@ -459,8 +459,10 @@ void _dns_client_period_run(void) list_for_each_entry(server_info, &client.dns_server_list, list) { if (server_info->last_send - 5 > server_info->last_recv) { - close(server_info->fd); - server_info->fd = 0; + if (server_info->fd > 0) { + close(server_info->fd); + server_info->fd = -1; + } } } pthread_mutex_unlock(&client.server_list_lock); @@ -482,13 +484,14 @@ static struct dns_query_struct *_dns_client_get_request(unsigned short sid, char pthread_mutex_lock(&client.domain_map_lock); hash_for_each_possible_safe(client.domain_map, query, tmp, domain_node, key) { + if (sid != query->sid) { + continue; + } + if (strncmp(query->domain, domain, DNS_MAX_CNAME_LEN) != 0) { continue; } - if (sid != query->sid) { - continue; - } query_result = query; break; } @@ -932,10 +935,11 @@ static int _dns_client_send_data_to_buffer(struct dns_server_info *server_info, return 0; } -static int _dns_client_send_tcp(struct dns_server_info *server_info, void *packet, int len) +static int _dns_client_send_tcp(struct dns_server_info *server_info, void *packet, unsigned short len) { int send_len = 0; - unsigned char inpacket[DNS_IN_PACKSIZE]; + unsigned char inpacket_data[DNS_IN_PACKSIZE]; + unsigned char *inpacket = inpacket_data; /* TCP query format * | len (short) | dns query data | @@ -1076,12 +1080,14 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void pthread_mutex_unlock(&client.domain_map_lock); /* send query */ + _dns_client_query_get(query); ret = _dns_client_send_query(query, domain); if (ret != 0) { goto errout_del_list; } tlog(TLOG_INFO, "send request %s, id %d\n", domain, query->sid); + _dns_client_query_release(query); return 0; errout_del_list: @@ -1090,6 +1096,7 @@ errout_del_list: list_del_init(&query->dns_request_list); hash_del(&query->domain_node); pthread_mutex_unlock(&client.domain_map_lock); + _dns_client_query_release(query); errout: if (query) { tlog(TLOG_ERROR, "release %p", query); diff --git a/src/fast_ping.c b/src/fast_ping.c index f9751b4..6b23a91 100644 --- a/src/fast_ping.c +++ b/src/fast_ping.c @@ -48,6 +48,7 @@ struct fast_ping_packet_msg { struct timeval tv; unsigned int sid; unsigned int seq; + unsigned int cookie; }; struct fast_ping_packet { @@ -76,6 +77,8 @@ struct ping_host_struct { int timeout; int count; int send; + int run; + unsigned int cookie; unsigned int sid; unsigned short port; unsigned short ss_family; @@ -258,13 +261,18 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host) tlog(TLOG_DEBUG, "ping %p end", ping_host); - memset(ping_host, 0, sizeof(*ping_host)); + // memset(ping_host, 0, sizeof(*ping_host)); + ping_host->type = FAST_PING_END; free(ping_host); } static void _fast_ping_host_remove(struct ping_host_struct *ping_host) { pthread_mutex_lock(&ping.map_lock); + if (!hash_hashed(&ping_host->addr_node)) { + pthread_mutex_unlock(&ping.map_lock); + return; + } hash_del(&ping_host->addr_node); pthread_mutex_unlock(&ping.map_lock); @@ -274,10 +282,9 @@ static void _fast_ping_host_remove(struct ping_host_struct *ping_host) tv.tv_usec = 0; ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tv, ping_host->userptr); - return; } - return _fast_ping_host_put(ping_host); + _fast_ping_host_put(ping_host); } static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) @@ -296,6 +303,7 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) gettimeofday(&packet->msg.tv, 0); packet->msg.sid = ping_host->sid; + packet->msg.cookie = ping_host->cookie; packet->msg.seq = ping_host->seq; icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); @@ -333,6 +341,7 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host) gettimeofday(&packet->msg.tv, 0); packet->msg.sid = ping_host->sid; packet->msg.seq = ping_host->seq; + packet->msg.cookie = ping_host->cookie; icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); len = sendto(ping.fd_icmp, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len); @@ -356,7 +365,7 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host) { struct epoll_event event; int flags; - int fd = 0; + int fd = -1; fd = socket(ping_host->ss_family, SOCK_STREAM, 0); if (fd < 0) { @@ -519,6 +528,8 @@ void fast_ping_print_result(struct ping_host_struct *ping_host, const char *host tlog(TLOG_INFO, "from %15s: seq=%d time=%.3f\n", host, seqno, rtt); } else if (result == PING_RESULT_TIMEOUT) { tlog(TLOG_INFO, "from %15s: seq=%d timeout\n", host, seqno); + } else if (result == PING_RESULT_END) { + fast_ping_stop(ping_host); } } @@ -535,6 +546,7 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv int port = -1; FAST_PING_TYPE type; int socktype = 0; + unsigned int seed; if (parse_ip(host, ip_str, &port) != 0) { goto errout; @@ -597,6 +609,9 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv atomic_set(&ping_host->ref, 0); atomic_set(&ping_host->notified, 0); ping_host->sid = atomic_inc_return(&ping_sid); + seed = ping_host->sid; + ping_host->cookie = rand_r(&seed); + ping_host->run = 0; if (ping_callback) { ping_host->ping_callback = ping_callback; } else { @@ -610,23 +625,25 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv goto errout; } memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen); + freeaddrinfo(gai); tlog(TLOG_DEBUG, "ping %s, id = %d", host, ping_host->sid); addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0); addrkey = jhash(&ping_host->sid, sizeof(ping_host->sid), addrkey); - _fast_ping_host_get(ping_host); - - if (_fast_ping_sendping(ping_host) != 0) { - goto errout; - } - - freeaddrinfo(gai); pthread_mutex_lock(&ping.map_lock); _fast_ping_host_get(ping_host); hash_add(ping.addrmap, &ping_host->addr_node, addrkey); pthread_mutex_unlock(&ping.map_lock); + _fast_ping_host_get(ping_host); + _fast_ping_host_get(ping_host); + if (_fast_ping_sendping(ping_host) != 0) { + goto errout_remove; + } + + ping_host->run = 1; + _fast_ping_host_put(ping_host); return ping_host; errout: if (gai) { @@ -637,6 +654,10 @@ errout: free(ping_host); } + return NULL; +errout_remove: + fast_ping_stop(ping_host); + _fast_ping_host_put(ping_host); return NULL; } @@ -755,6 +776,7 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti struct timeval *tvsend = NULL; unsigned int sid; unsigned int seq; + unsigned int cookie; len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len); if (len < 0) { @@ -773,11 +795,13 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti tvsend = &packet->msg.tv; sid = packet->msg.sid; seq = packet->msg.seq; + cookie = packet->msg.cookie; addrkey = jhash(&sid, sizeof(sid), addrkey); pthread_mutex_lock(&ping.map_lock); hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey) { - if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid) { + if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid && + recv_ping_host->cookie == cookie) { break; } } @@ -862,7 +886,10 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_e break; case FAST_PING_TCP: ret = _fast_ping_process_tcp(ping_host, event, now); + break; default: + tlog(TLOG_ERROR, "BUG: type error : %d,", ping_host->type); + abort(); break; } @@ -906,6 +933,10 @@ static void _fast_ping_period_run(void) pthread_mutex_lock(&ping.map_lock); hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node) { + if (ping_host->run == 0) { + continue; + } + interval = now; tv_sub(&interval, &ping_host->last); millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000; diff --git a/src/fast_ping.h b/src/fast_ping.h index 516292b..5edfde2 100644 --- a/src/fast_ping.h +++ b/src/fast_ping.h @@ -11,7 +11,8 @@ typedef enum { FAST_PING_ICMP = 1, FAST_PING_ICMP6 = 2, FAST_PING_TCP, - FAST_PING_UDP + FAST_PING_UDP, + FAST_PING_END } FAST_PING_TYPE; typedef enum { diff --git a/src/include/art.h b/src/include/art.h index 184e643..376af20 100644 --- a/src/include/art.h +++ b/src/include/art.h @@ -149,7 +149,7 @@ int art_tree_destroy(art_tree *t); #ifdef BROKEN_GCC_C99_INLINE # define art_size(t) ((t)->size) #else -inline uint64_t art_size(art_tree *t) { +static inline uint64_t art_size(art_tree *t) { return t->size; } #endif diff --git a/src/lib/art.c b/src/lib/art.c index 60a51fe..9a4684d 100644 --- a/src/lib/art.c +++ b/src/lib/art.c @@ -421,7 +421,8 @@ static void add_child48(art_node48 *n, art_node **ref, unsigned char c, void *ch n->n.num_children++; } else { art_node256 *new_node = (art_node256*)alloc_node(NODE256); - for (int i=0;i<256;i++) { + int i; + for (i=0;i<256;i++) { if (n->keys[i]) { new_node->children[i] = n->children[n->keys[i] - 1]; } @@ -460,7 +461,8 @@ static void add_child16(art_node16 *n, art_node **ref, unsigned char c, void *ch #else // Compare the key to all 16 stored keys unsigned bitfield = 0; - for (short i = 0; i < 16; ++i) { + int i; + for (i = 0; i < 16; ++i) { if (c < n->keys[i]) bitfield |= (1 << i); } @@ -487,11 +489,12 @@ static void add_child16(art_node16 *n, art_node **ref, unsigned char c, void *ch } else { art_node48 *new_node = (art_node48*)alloc_node(NODE48); + int i; - // Copy the child pointers and populate the key map + // Copy the child pointers and populate the key map memcpy(new_node->children, n->children, sizeof(void*)*n->n.num_children); - for (int i=0;in.num_children;i++) { + for (i=0;in.num_children;i++) { new_node->keys[n->keys[i]] = i + 1; } copy_header((art_node*)new_node, (art_node*)n); @@ -685,7 +688,8 @@ static void remove_child256(art_node256 *n, art_node **ref, unsigned char c) { copy_header((art_node*)new_node, (art_node*)n); int pos = 0; - for (int i=0;i<256;i++) { + int i; + for (i=0;i<256;i++) { if (n->children[i]) { new_node->children[pos] = n->children[i]; new_node->keys[i] = pos + 1; @@ -708,7 +712,8 @@ static void remove_child48(art_node48 *n, art_node **ref, unsigned char c) { copy_header((art_node*)new_node, (art_node*)n); int child = 0; - for (int i=0;i<256;i++) { + int i; + for (i=0;i<256;i++) { pos = n->keys[i]; if (pos) { new_node->keys[child] = i; @@ -853,23 +858,24 @@ static int recursive_iter(art_node *n, art_callback cb, void *data) { } int idx, res; - switch (n->type) { + int i; + switch (n->type) { case NODE4: - for (int i=0; i < n->num_children; i++) { + for (i=0; i < n->num_children; i++) { res = recursive_iter(((art_node4*)n)->children[i], cb, data); if (res) return res; } break; case NODE16: - for (int i=0; i < n->num_children; i++) { + for (i=0; i < n->num_children; i++) { res = recursive_iter(((art_node16*)n)->children[i], cb, data); if (res) return res; } break; case NODE48: - for (int i=0; i < 256; i++) { + for (i=0; i < 256; i++) { idx = ((art_node48*)n)->keys[i]; if (!idx) continue; @@ -879,7 +885,7 @@ static int recursive_iter(art_node *n, art_callback cb, void *data) { break; case NODE256: - for (int i=0; i < 256; i++) { + for (i=0; i < 256; i++) { if (!((art_node256*)n)->children[i]) continue; res = recursive_iter(((art_node256*)n)->children[i], cb, data); if (res) return res; diff --git a/src/tlog.c b/src/tlog.c index 98cdb67..283b329 100644 --- a/src/tlog.c +++ b/src/tlog.c @@ -287,16 +287,16 @@ int tlog_vext(tlog_level level, const char *file, int line, const char *func, vo int len; int maxlen = 0; + if (level < tlog_set_level) { + return 0; + } + if (tlog.buff == NULL) { vprintf(format, ap); printf("\n"); return -1; } - if (level < tlog_set_level) { - return 0; - } - pthread_mutex_lock(&tlog.lock); do { if (tlog.end == tlog.start) {