]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: don't send data after closing connection
authorQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 26 Apr 2018 04:29:40 +0000 (00:29 -0400)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Tue, 29 May 2018 19:06:16 +0000 (19:06 +0000)
Cancelling threads is nice but they can potentially be scheduled again
after cancellation without an explicit check.

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
zebra/zserv.c
zebra/zserv.h

index 1effb2b2b4d0de0213d7cf7841521dd18d341845..548e0b32c0cdddb33dfcf078721375c1ba1717d3 100644 (file)
@@ -53,6 +53,7 @@
 #include "lib/zassert.h"          /* for assert */
 #include "lib/zclient.h"          /* for zmsghdr, ZEBRA_HEADER_SIZE, ZEBRA... */
 #include "lib/frr_pthread.h"      /* for frr_pthread_new, frr_pthread_stop... */
+#include "lib/frratomic.h"        /* for atomic_load_explicit, atomic_stor... */
 
 #include "zebra/debug.h"          /* for various debugging macros */
 #include "zebra/rib.h"            /* for rib_score_proto */
@@ -166,6 +167,7 @@ static void zserv_log_message(const char *errmsg, struct stream *msg,
  */
 static void zserv_client_close(struct zserv *client)
 {
+       atomic_store_explicit(&client->dead, true, memory_order_seq_cst);
        THREAD_OFF(client->t_read);
        THREAD_OFF(client->t_write);
        zserv_event(client, ZSERV_HANDLE_CLOSE);
@@ -199,6 +201,9 @@ static int zserv_write(struct thread *thread)
        int writerv;
        struct stream_fifo *cache;
 
+       if (atomic_load_explicit(&client->dead, memory_order_seq_cst))
+               return 0;
+
        /* If we have any data pending, try to flush it first */
        switch (buffer_flush_available(client->wb, client->sock)) {
        case BUFFER_ERROR:
@@ -286,18 +291,23 @@ zwrite_fail:
  */
 static int zserv_read(struct thread *thread)
 {
+       struct zserv *client = THREAD_ARG(thread);
        int sock;
-       struct zserv *client;
        size_t already;
-       struct stream_fifo *cache = stream_fifo_new();
-       uint32_t p2p_orig = atomic_load_explicit(&zebrad.packets_to_process,
-                                                memory_order_relaxed);
+       struct stream_fifo *cache;
+       uint32_t p2p_orig;
+
        uint32_t p2p;
        struct zmsghdr hdr;
 
+       if (atomic_load_explicit(&client->dead, memory_order_seq_cst))
+               return 0;
+
+       p2p_orig = atomic_load_explicit(&zebrad.packets_to_process,
+                                       memory_order_relaxed);
+       cache = stream_fifo_new();
        p2p = p2p_orig;
        sock = THREAD_FD(thread);
-       client = THREAD_ARG(thread);
 
        while (p2p) {
                ssize_t nb;
@@ -435,6 +445,9 @@ zread_fail:
 static void zserv_client_event(struct zserv *client,
                               enum zserv_client_event event)
 {
+       if (atomic_load_explicit(&client->dead, memory_order_seq_cst))
+               return;
+
        switch (event) {
        case ZSERV_CLIENT_READ:
                thread_add_read(client->pthread->master, zserv_read, client,
index a1b55bf8ebe0cce6d3f53b8ac167af6d57f0bc39..c8b65b6a4eb1e25827a03cb904267b5207a500f1 100644 (file)
@@ -53,6 +53,9 @@ struct zserv {
        /* Client pthread */
        struct frr_pthread *pthread;
 
+       /* Whether the thread is waiting to be killed */
+       _Atomic bool dead;
+
        /* Client file descriptor. */
        int sock;