]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Test if linked while holding the queue lock
authorMark Andrews <marka@isc.org>
Thu, 27 Aug 2020 10:40:08 +0000 (20:40 +1000)
committerMark Andrews <marka@isc.org>
Mon, 7 Sep 2020 23:25:43 +0000 (09:25 +1000)
WARNING: ThreadSanitizer: data race
  Read of size 8 at 0x000000000001 by thread T1:
    #0 client_shutdown bin/named/client.c:849:6
    #1 dispatch lib/isc/task.c:1157:7
    #2 run lib/isc/task.c:1331:2

  Previous write of size 8 at 0x000000000001 by thread T2 (mutexes: write M1, write M2):
    #0 client_shutdown bin/named/client.c:850:3
    #1 dispatch lib/isc/task.c:1157:7
    #2 run lib/isc/task.c:1331:2

bin/named/client.c
lib/isc/include/isc/queue.h

index 8b3227ad623b624cf51ad0841986c48a3535383b..978e4d91b8dc713808e4abc3585c0276c444fbe3 100644 (file)
@@ -850,8 +850,7 @@ client_shutdown(isc_task_t *task, isc_event_t *event) {
                client->shutdown_arg = NULL;
        }
 
-       if (ISC_QLINK_LINKED(client, ilink))
-               ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink);
+       ISC_QUEUE_UNLINKIFLINKED(client->manager->inactive, client, ilink);
 
        client->newstate = NS_CLIENTSTATE_FREED;
        client->needshutdown = false;
index d682ba49403236ece9abad62f05dd8ca2370c59b..416cefcb5d0137a81a3432a65ea3ffce09ba553b 100644 (file)
                (elt)->link.next = (elt)->link.prev = (void *)(-1); \
        } while(0)
 
+#define ISC_QUEUE_UNLINKIFLINKED(queue, elt, link) \
+       do { \
+               LOCK(&(queue).headlock); \
+               LOCK(&(queue).taillock); \
+               if (ISC_QLINK_LINKED(elt, link)) { \
+                       if ((elt)->link.prev == NULL) \
+                               (queue).head = (elt)->link.next; \
+                       else \
+                               (elt)->link.prev->link.next = (elt)->link.next; \
+                       if ((elt)->link.next == NULL) \
+                               (queue).tail = (elt)->link.prev; \
+                       else \
+                               (elt)->link.next->link.prev = (elt)->link.prev; \
+               } \
+               UNLOCK(&(queue).taillock); \
+               UNLOCK(&(queue).headlock); \
+               (elt)->link.next = (elt)->link.prev = (void *)(-1); \
+       } while(0)
+
 #endif /* ISC_QUEUE_H */