Ver Fonte

dns_cache: try to fix crash issue.

Nick Peng há 3 meses atrás
pai
commit
48e439da74
2 ficheiros alterados com 17 adições e 10 exclusões
  1. 8 2
      src/dns_cache.c
  2. 9 8
      src/lib/timer_wheel.c

+ 8 - 2
src/dns_cache.c

@@ -121,11 +121,16 @@ void dns_cache_get(struct dns_cache *dns_cache)
 
 void dns_cache_release(struct dns_cache *dns_cache)
 {
+	int refcnt = 0;
 	if (dns_cache == NULL) {
 		return;
 	}
 
-	if (!atomic_dec_and_test(&dns_cache->ref)) {
+	refcnt = atomic_dec_return(&dns_cache->ref);
+	if (refcnt > 0) {
+		return;
+	} else if (refcnt < 0) {
+		BUG("dns_cache refcnt is invalid: %d", refcnt);
 		return;
 	}
 
@@ -134,6 +139,7 @@ void dns_cache_release(struct dns_cache *dns_cache)
 
 static void _dns_cache_remove(struct dns_cache *dns_cache)
 {
+	dns_cache->del_pending = 0;
 	hash_del(&dns_cache->node);
 	list_del_init(&dns_cache->list);
 	dns_timer_del(&dns_cache->timer);
@@ -178,7 +184,7 @@ struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len
 static void dns_cache_timer_release(struct tw_base *base, struct tw_timer_list *timer, void *data)
 {
 	struct dns_cache *dns_cache = data;
-	dns_cache_delete(dns_cache);
+	dns_cache_release(dns_cache);
 }
 
 static void dns_cache_expired(struct tw_base *base, struct tw_timer_list *timer, void *data, unsigned long timestamp)

+ 9 - 8
src/lib/timer_wheel.c

@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
- #define _GNU_SOURCE
+#define _GNU_SOURCE
 
 #include "smartdns/lib/bitops.h"
 #include <pthread.h>
@@ -169,7 +169,6 @@ void tw_add_timer(struct tw_base *base, struct tw_timer_list *timer)
 int tw_del_timer(struct tw_base *base, struct tw_timer_list *timer)
 {
 	int ret = 0;
-	int call_del = 0;
 
 	pthread_spin_lock(&base->lock);
 	{
@@ -177,16 +176,16 @@ int tw_del_timer(struct tw_base *base, struct tw_timer_list *timer)
 			ret = 1;
 			_tw_detach_timer(timer);
 			if (timer->del_function) {
-				call_del = 1;
+				tw_del_func del_func = timer->del_function;
+				timer->del_function = NULL;
+				pthread_spin_unlock(&base->lock);
+				del_func(base, timer, timer->data);
+				pthread_spin_lock(&base->lock);
 			}
 		}
 	}
 	pthread_spin_unlock(&base->lock);
 
-	if (call_del) {
-		timer->del_function(base, timer, timer->data);
-	}
-
 	return ret;
 }
 
@@ -287,8 +286,10 @@ static inline void run_timers(struct tw_base *base)
 
 			pthread_spin_lock(&base->lock);
 			if ((timer_pending(timer) == 0 && timer->del_function)) {
+				tw_del_func del_func = timer->del_function;
+				timer->del_function = NULL;
 				pthread_spin_unlock(&base->lock);
-				timer->del_function(base, timer, timer->data);
+				del_func(base, timer, timer->data);
 				pthread_spin_lock(&base->lock);
 			}
 		}