Protect closeconv() with waserror()
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 2 Sep 2016 17:25:40 +0000 (13:25 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 6 Sep 2016 13:26:23 +0000 (09:26 -0400)
If closeconv() calls something that throws, it wouldn't unlock.

I didn't see closeconv get jumped over without unlocking, but it was a
potential source of deadlock.  From looking at the code, this is possible:

closeconv() ->
  ipifcremmulti() ->
    remselfcache() ->
      etherremmulit() ->
        devtab[x].write()

The latter call can throw.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/net/devip.c

index 2bc6160..59321e2 100644 (file)
@@ -668,6 +668,7 @@ static char *ipchaninfo(struct chan *ch, char *ret, size_t ret_l)
 
 static void closeconv(struct conv *cv)
 {
+       ERRSTACK(1);
        struct conv *nc;
        struct Ipmulti *mp;
 
@@ -677,7 +678,10 @@ static void closeconv(struct conv *cv)
                qunlock(&cv->qlock);
                return;
        }
-
+       if (waserror()) {
+               qunlock(&cv->qlock);
+               nexterror();
+       }
        /* close all incoming calls since no listen will ever happen */
        for (nc = cv->incall; nc; nc = cv->incall) {
                cv->incall = nc->next;
@@ -696,6 +700,7 @@ static void closeconv(struct conv *cv)
        cv->p->close(cv);
        cv->state = Idle;
        qunlock(&cv->qlock);
+       poperror();
 }
 
 static void ipclose(struct chan *c)