Fix race between final conn_put() and mrpc_conn_set_destroy()
Fix race between final conn_put() and mrpc_conn_set_destroy()

- The final conn_put() was decrementing the refcount and then calling
mrpc_conn_free(), which would remove the conn from conn->set->conns.  In the
interim, mrpc_conn_set_destroy() could come in and try to call
mrpc_conn_close() on the conn, which would assert because the conn's
refcount was zero.  In conn_put(), we now atomically decrement the refcount
and remove the conn->set->conns link (if necessary).

- Remove connections from set->conns *as* we walk the list in
mrpc_conn_set_destroy(), and handle the case (in conn_put()) where we're
freeing a connection that has already been removed from the list.  This
allows us to drop the conns_lock in mrpc_conn_set_destroy() while we're
calling into mrpc_conn_close(), so that we don't deadlock when that function
calls conn_put().

cmusatyalab/minirpc,cmusatyalab/minirpc