On Mon, Nov 06, 2017 at 03:19:25PM +0100, Olivier Houchard wrote:
> Hi,
> 
> The attached patch fixes a locking issue that prevented SRV records from
> working.
> 
> Regards,
> 
> Olivier
> 


And another one, that fix a deadlock that occurs when checks trigger DNs
resolutoin.

Regards,

Olivier
>From 3cedd71b5338f8689004837cdcaa0ae42e48e39c Mon Sep 17 00:00:00 2001
From: Olivier Houchard <[email protected]>
Date: Mon, 6 Nov 2017 17:30:28 +0100
Subject: [PATCH] BUG/MINOR: dns: Don't lock the server lock in
 snr_check_ip_callback().

snr_check_ip_callback() may be called with the server lock, so don't attempt
to lock it again, instead, make sure the callers always have the lock before
calling it.
---
 src/dns.c    |  6 ++++++
 src/server.c | 10 ++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/dns.c b/src/dns.c
index 1d12c8421..0f93f3ce5 100644
--- a/src/dns.c
+++ b/src/dns.c
@@ -1614,7 +1614,13 @@ static void dns_resolve_recv(struct dgram_conn *dgram)
                 * from the cache */
                tmpns = ns;
                list_for_each_entry(req, &res->requesters, list) {
+                       struct server *s = objt_server(req->owner);
+
+                       if (s)
+                               SPIN_LOCK(SERVER_LOCK, &s->lock);
                        req->requester_cb(req, tmpns);
+                       if (s)
+                               SPIN_UNLOCK(SERVER_LOCK, &s->lock);
                        tmpns = NULL;
                }
 
diff --git a/src/server.c b/src/server.c
index adc9fd40c..1a78fb334 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3589,6 +3589,8 @@ int snr_update_srv_status(struct server *s, int has_no_ip)
  * returns:
  *  0 on error
  *  1 when no error or safe ignore
+ *
+ * Must be called with server lock held
  */
 int snr_resolution_cb(struct dns_requester *requester, struct dns_nameserver 
*nameserver)
 {
@@ -3694,7 +3696,9 @@ int snr_resolution_error_cb(struct dns_requester 
*requester, int error_code)
        s = objt_server(requester->owner);
        if (!s)
                return 1;
+       SPIN_LOCK(SERVER_LOCK, &s->lock);
        snr_update_srv_status(s, 0);
+       SPIN_UNLOCK(SERVER_LOCK, &s->lock);
        return 1;
 }
 
@@ -3703,6 +3707,8 @@ int snr_resolution_error_cb(struct dns_requester 
*requester, int error_code)
  * which owns <srv> and is up.
  * It returns a pointer to the first server found or NULL if <ip> is not yet
  * assigned.
+ *
+ * Must be called with server lock held
  */
 struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned 
char *ip_family)
 {
@@ -3712,8 +3718,6 @@ struct server *snr_check_ip_callback(struct server *srv, 
void *ip, unsigned char
        if (!srv)
                return NULL;
 
-       SPIN_LOCK(SERVER_LOCK, &srv->lock);
-
        be = srv->proxy;
        for (tmpsrv = be->srv; tmpsrv; tmpsrv = tmpsrv->next) {
                /* we found the current server is the same, ignore it */
@@ -3751,13 +3755,11 @@ struct server *snr_check_ip_callback(struct server 
*srv, void *ip, unsigned char
                     (tmpsrv->addr.ss_family == AF_INET6 &&
                      memcmp(ip, &((struct sockaddr_in6 
*)&tmpsrv->addr)->sin6_addr, 16) == 0))) {
                        SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
-                       SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
                        return tmpsrv;
                }
                SPIN_UNLOCK(SERVER_LOCK, &tmpsrv->lock);
        }
 
-       SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
 
        return NULL;
 }
-- 
2.13.5

Reply via email to