From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:38160) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T60o2-0005KG-M8 for qemu-devel@nongnu.org; Mon, 27 Aug 2012 11:00:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T60nw-0005bk-GN for qemu-devel@nongnu.org; Mon, 27 Aug 2012 11:00:46 -0400 Received: from mail-ee0-f45.google.com ([74.125.83.45]:54960) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T60nw-0005Yi-9s for qemu-devel@nongnu.org; Mon, 27 Aug 2012 11:00:40 -0400 Received: by mail-ee0-f45.google.com with SMTP id e53so1535391eek.4 for ; Mon, 27 Aug 2012 08:00:39 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Mon, 27 Aug 2012 17:00:16 +0200 Message-Id: <1346079626-16386-4-git-send-email-pbonzini@redhat.com> In-Reply-To: <1346079626-16386-1-git-send-email-pbonzini@redhat.com> References: <1346079626-16386-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [RFC PATCH 03/13] nbd: do not leak nbd_trip coroutines when a connection is torn down List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, stefanha@gmail.com Because nbd_client_close removes the I/O handlers for the client socket, there is no way that any suspended coroutines are restarted. This will be a problem with the QEMU embedded NBD server, because we will have a QMP command to forcibly close all connections with the clients. Instead, we can exploit the reference counting of NBDClients; shutdown the client socket, which will make it readable and writeable. The coroutines then will fail and exit cleanly. The last refcount finally triggers the closure of the client. Signed-off-by: Paolo Bonzini --- nbd.c | 18 +++++++++++------- nbd.h | 3 +++ 2 file modificati, 14 inserzioni(+), 7 rimozioni(-) diff --git a/nbd.c b/nbd.c index c1edbeb..cb4e8fe 100644 --- a/nbd.c +++ b/nbd.c @@ -657,18 +657,22 @@ static void nbd_client_get(NBDClient *client) static void nbd_client_put(NBDClient *client) { if (--client->refcount == 0) { + qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); + close(client->sock); + client->sock = -1; + if (client->close) { + client->close(client); + } g_free(client); } } -static void nbd_client_close(NBDClient *client) +void nbd_client_close(NBDClient *client) { - qemu_set_fd_handler2(client->sock, NULL, NULL, NULL, NULL); - close(client->sock); - client->sock = -1; - if (client->close) { - client->close(client); - } + /* Force requests to finish. They will drop their own references, + * then we'll close the socket and free the NBDClient. + */ + shutdown(client->sock, 2); nbd_client_put(client); } diff --git a/nbd.h b/nbd.h index 40d58d3..6305d68 100644 --- a/nbd.h +++ b/nbd.h @@ -81,7 +81,10 @@ typedef struct NBDClient NBDClient; NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, off_t size, uint32_t nbdflags); void nbd_export_close(NBDExport *exp); + NBDClient *nbd_client_new(NBDExport *exp, int csock, void (*close)(NBDClient *)); +void nbd_client_close(NBDClient *client); + #endif -- 1.7.11.2