]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Coro: Fixed deadlock when CLI is killed.
authorJan Maria Matejka <mq@ucw.cz>
Tue, 28 Aug 2018 14:45:07 +0000 (16:45 +0200)
committerJan Maria Matejka <mq@ucw.cz>
Tue, 28 Aug 2018 14:49:43 +0000 (16:49 +0200)
lib/coroutine.h
lib/socket.h
nest/cli.c
sysdep/unix/coroutine.c

index f64a9540b6551370cdfe1ec4cbd325e83182f2d4..93a41233a8cbfdbb4d8f70e21228ee9c7cc16d57 100644 (file)
@@ -18,5 +18,6 @@ void coro_resume(coroutine *c);
 
 struct birdsock;
 int coro_sk_read(struct birdsock *s);
+void coro_sk_write(struct birdsock *s, unsigned len);
 
 #endif
index 00e4a29c90fc33b00f47df6c3c0cfab7fdef27f3..d961841ebb03bb4b535370b51db23fe1cde197e1 100644 (file)
@@ -83,6 +83,7 @@ typedef struct birdsock {
   struct ssh_sock *ssh;                        /* Used in SK_SSH */
 
   struct coroutine *rx_coroutine;
+  struct coroutine *tx_coroutine;
 } sock;
 
 sock *sock_new(pool *);                        /* Allocate new socket */
index 986b28805a2f732e13cf36a054206badce5c9d4a..f4b7628ca89b0ed86713e0d8cc6a66b0416bad4a 100644 (file)
@@ -245,8 +245,7 @@ cli_write(cli *c)
       s->tbuf = o->outpos;
       o->outpos = o->wpos;
 
-      if (sk_send(s, len) <= 0)
-       return;
+      coro_sk_write(s, len);
 
       c->tx_pos = o->next;
     }
@@ -264,12 +263,6 @@ cli_write_trigger(cli *c)
     cli_write(c);
 }
 
-static void
-cli_tx_hook(sock *s)
-{
-  cli_write(s->data);
-}
-
 static void
 cli_err_hook(sock *s, int err)
 {
@@ -540,7 +533,6 @@ cli_new(sock *s)
 
   s->pool = c->pool;           /* We need to have all the socket buffers allocated in the cli pool */
   rmove(s, c->pool);
-  s->tx_hook = cli_tx_hook;
   s->err_hook = cli_err_hook;
   s->data = c;
 
index c5a2ba7390610b0ad026fcf5c6fec713b069739d..fc650a57dbe750fdc4ee1ce8c34930bb5917e443 100644 (file)
@@ -146,6 +146,7 @@ static void
 coro_free(resource *r)
 {
   coroutine *c = (coroutine *) r;
+  ASSERT(coro_current != c);
   pthread_cancel(c->thread);
   pthread_join(c->thread, NULL);
 }
@@ -246,6 +247,14 @@ coro_sk_rx_hook(sock *sk, uint size UNUSED)
   return 0;
 }
 
+static void
+coro_sk_tx_hook(sock *sk)
+{
+  ASSERT(sk->tx_coroutine);
+  ASSERT(!coro_current);
+  coro_resume(sk->tx_coroutine);
+}
+
 int
 coro_sk_read(sock *s)
 {
@@ -256,3 +265,15 @@ coro_sk_read(sock *s)
   s->rx_hook = NULL;
   return s->rpos - s->rbuf;
 }
+
+void
+coro_sk_write(sock *s, unsigned len)
+{
+  ASSERT(coro_current);
+  s->tx_coroutine = coro_current;
+  s->tx_hook = coro_sk_tx_hook;
+  s->ttx = s->tbuf;
+  s->tpos = s->tbuf + len;
+  coro_suspend();
+  s->tx_hook = NULL;
+}