sel/bres.c (zap): Don't scramble the freelist when a query is aborted.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 19 Jul 2014 16:14:11 +0000 (17:14 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 19 Jul 2014 16:14:11 +0000 (17:14 +0100)
If a query is aborted after it's been committed to a server process,
then we kill the server and return its control block to the freelist.
Unfortunately, the function which does this, `zap', unconditionally
tries to unlink the control block from its current position in the
freelist; but it wasn't actually there before.  The result is that
another server control block might be linked back into the freelist.
Attaching a second client to it while it's already in use fails when
`attach' tries to remove the server's idle timer, which isn't active: at
this point, we get a segfault.

sel/bres.c

index 2885d0e..cc44049 100644 (file)
@@ -591,7 +591,7 @@ static void zap(bres_server *rs)
 
   /* --- Move the server to the back of the list --- */
 
-  UNLINK(freelist, freetail, rs);
+  if (!rs->rc) UNLINK(freelist, freetail, rs);
   LINKTAIL(freelist, freetail, rs);
 }