From db4840564d3c77c071247d6cdb1e7c9fb55f16a5 Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Tue, 8 Nov 2022 21:45:20 +0800 Subject: [PATCH] dns: Reduce the dns_lock granularity When a7 curl calls dns_query via usrsock, it will wait a usrsock response with the dns lock held. If a7 rptun recv a dns_addnameserver event from another core at this time, rptun waits the lock held by curl in callback. Then curl will never get its usrsock response with rptun blocked, so the deadlock occurs. This change will break lock when do usrsock request. Signed-off-by: zhanghongyu --- libs/libc/netdb/lib_dns.h | 20 ++++++++++++++++++++ libs/libc/netdb/lib_dnsforeach.c | 10 ++++++++++ libs/libc/netdb/lib_dnsinit.c | 27 ++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/libs/libc/netdb/lib_dns.h b/libs/libc/netdb/lib_dns.h index 25ed4fedf1..996bc8683f 100644 --- a/libs/libc/netdb/lib_dns.h +++ b/libs/libc/netdb/lib_dns.h @@ -151,6 +151,26 @@ void dns_lock(void); void dns_unlock(void); +/**************************************************************************** + * Name: dns_breaklock + * + * Description: + * Break the DNS lock + * + ****************************************************************************/ + +void dns_breaklock(FAR unsigned int *count); + +/**************************************************************************** + * Name: dns_restorelock + * + * Description: + * Restore the DNS lock + * + ****************************************************************************/ + +void dns_restorelock(unsigned int count); + /**************************************************************************** * Name: dns_bind * diff --git a/libs/libc/netdb/lib_dnsforeach.c b/libs/libc/netdb/lib_dnsforeach.c index 5ce67f4aee..75d4e58cf2 100644 --- a/libs/libc/netdb/lib_dnsforeach.c +++ b/libs/libc/netdb/lib_dnsforeach.c @@ -80,6 +80,7 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) char line[DNS_MAX_LINE]; FAR char *addrstr; FAR char *ptr; + unsigned int count; uint16_t port; int keylen; int ret; @@ -186,8 +187,10 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) { u.ipv4.sin_family = AF_INET; u.ipv4.sin_port = port; + dns_breaklock(&count); ret = callback(arg, (FAR struct sockaddr *)&u.ipv4, sizeof(struct sockaddr_in)); + dns_restorelock(count); } else #endif @@ -205,8 +208,10 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) { u.ipv6.sin6_family = AF_INET6; u.ipv6.sin6_port = port; + dns_breaklock(&count); ret = callback(arg, (FAR struct sockaddr *)&u.ipv6, sizeof(struct sockaddr_in6)); + dns_restorelock(count); } else #endif @@ -235,6 +240,7 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) { FAR struct sockaddr *addr; + unsigned int count; int ret = OK; int i; @@ -255,7 +261,9 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) /* Perform the callback */ + dns_breaklock(&count); ret = callback(arg, addr, sizeof(struct sockaddr_in)); + dns_restorelock(count); } else #endif @@ -274,7 +282,9 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg) /* Perform the callback */ + dns_breaklock(&count); ret = callback(arg, addr, sizeof(struct sockaddr_in6)); + dns_restorelock(count); } else #endif diff --git a/libs/libc/netdb/lib_dnsinit.c b/libs/libc/netdb/lib_dnsinit.c index 4d78b03b6d..4ce1dc7c26 100644 --- a/libs/libc/netdb/lib_dnsinit.c +++ b/libs/libc/netdb/lib_dnsinit.c @@ -43,7 +43,7 @@ static rmutex_t g_dns_lock = NXRMUTEX_INITIALIZER; /**************************************************************************** - * Private Functions + * Public Functions ****************************************************************************/ /**************************************************************************** @@ -71,3 +71,28 @@ void dns_unlock(void) { nxrmutex_unlock(&g_dns_lock); } + +/**************************************************************************** + * Name: dns_breaklock + * + * Description: + * Break the DNS lock + ****************************************************************************/ + +void dns_breaklock(FAR unsigned int *count) +{ + nxrmutex_breaklock(&g_dns_lock, count); +} + +/**************************************************************************** + * Name: dns_restorelock + * + * Description: + * Restore the DNS lock + * + ****************************************************************************/ + +void dns_restorelock(unsigned int count) +{ + nxrmutex_restorelock(&g_dns_lock, count); +}