[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v2 4/4] qemu-char: do not operate on sources fro
From: |
Sander Eikelenboom |
Subject: |
Re: [Qemu-devel] [PATCH v2 4/4] qemu-char: do not operate on sources from finalize callbacks |
Date: |
Fri, 19 Apr 2013 19:12:29 +0200 |
Friday, April 19, 2013, 5:32:09 PM, you wrote:
> Due to a glib bug, the finalize callback is called with the GMainContext
> lock held. Thus, any operation on the context from the callback will
> cause recursive locking and a deadlock. This happens, for example,
> when a client disconnects from a socket chardev.
> The fix for this is somewhat ugly, because we need to forego polymorphism
> and implement our own function to destroy IOWatchPoll sources. The
> right thing to do here would be child sources, but we support older
> glib versions that do not have them. Not coincidentially, glib developers
> found and fixed the deadlock as part of implementing child sources.
> Signed-off-by: Paolo Bonzini <address@hidden>
Tested-by: Sander Eikelenboom <address@hidden>
> ---
> qemu-char.c | 55 ++++++++++++++++++++++++++++++++++++++++---------------
> 1 files changed, 40 insertions(+), 15 deletions(-)
> diff --git a/qemu-char.c b/qemu-char.c
> index 6e897da..f29f9b1 100644
> --- a/qemu-char.c
> +++ b/qemu-char.c
> @@ -643,12 +643,18 @@ static gboolean io_watch_poll_dispatch(GSource *source,
> GSourceFunc callback,
>
> static void io_watch_poll_finalize(GSource *source)
> {
> + /* Due to a glib bug, removing the last reference to a source
> + * inside a finalize callback causes recursive locking (and a
> + * deadlock). This is not a problem inside other callbacks,
> + * including dispatch callbacks, so we call io_remove_watch_poll
> + * to remove this source. At this point, iwp->src must
> + * be NULL, or we would leak it.
> + *
> + * This would be solved much more elegantly by child sources,
> + * but we support older glib versions that do not have them.
> + */
> IOWatchPoll *iwp = io_watch_poll_from_source(source);
- if (iwp->>src) {
> - g_source_destroy(iwp->src);
> - g_source_unref(iwp->src);
- iwp->>src = NULL;
> - }
+ assert(iwp->>src == NULL);
> }
>
> static GSourceFuncs io_watch_poll_funcs = {
> @@ -679,6 +685,25 @@ static guint io_add_watch_poll(GIOChannel *channel,
> return tag;
> }
>
> +static void io_remove_watch_poll(guint tag)
> +{
> + GSource *source;
> + IOWatchPoll *iwp;
> +
> + g_return_if_fail (tag > 0);
> +
> + source = g_main_context_find_source_by_id(NULL, tag);
> + g_return_if_fail (source != NULL);
> +
> + iwp = io_watch_poll_from_source(source);
+ if (iwp->>src) {
> + g_source_destroy(iwp->src);
> + g_source_unref(iwp->src);
+ iwp->>src = NULL;
> + }
> + g_source_destroy(&iwp->parent);
> +}
> +
> #ifndef _WIN32
> static GIOChannel *io_channel_from_fd(int fd)
> {
> @@ -788,7 +813,7 @@ static gboolean fd_chr_read(GIOChannel *chan,
> GIOCondition cond, void *opaque)
> len, &bytes_read, NULL);
> if (status == G_IO_STATUS_EOF) {
> if (s->fd_in_tag) {
> - g_source_remove(s->fd_in_tag);
> + io_remove_watch_poll(s->fd_in_tag);
> s->fd_in_tag = 0;
> }
> qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
> @@ -821,7 +846,7 @@ static void fd_chr_update_read_handler(CharDriverState
> *chr)
> FDCharDriver *s = chr->opaque;
>
> if (s->fd_in_tag) {
> - g_source_remove(s->fd_in_tag);
> + io_remove_watch_poll(s->fd_in_tag);
> s->fd_in_tag = 0;
> }
>
> @@ -835,7 +860,7 @@ static void fd_chr_close(struct CharDriverState *chr)
> FDCharDriver *s = chr->opaque;
>
> if (s->fd_in_tag) {
> - g_source_remove(s->fd_in_tag);
> + io_remove_watch_poll(s->fd_in_tag);
> s->fd_in_tag = 0;
> }
>
> @@ -1145,7 +1170,7 @@ static void pty_chr_state(CharDriverState *chr, int
> connected)
>
> if (!connected) {
> if (s->fd_tag) {
> - g_source_remove(s->fd_tag);
> + io_remove_watch_poll(s->fd_tag);
> s->fd_tag = 0;
> }
> s->connected = 0;
> @@ -1173,7 +1198,7 @@ static void pty_chr_close(struct CharDriverState *chr)
> int fd;
>
> if (s->fd_tag) {
> - g_source_remove(s->fd_tag);
> + io_remove_watch_poll(s->fd_tag);
> s->fd_tag = 0;
> }
> fd = g_io_channel_unix_get_fd(s->fd);
> @@ -2252,7 +2277,7 @@ static gboolean udp_chr_read(GIOChannel *chan,
> GIOCondition cond, void *opaque)
> s->bufptr = s->bufcnt;
> if (status != G_IO_STATUS_NORMAL) {
> if (s->tag) {
> - g_source_remove(s->tag);
> + io_remove_watch_poll(s->tag);
> s->tag = 0;
> }
> return FALSE;
> @@ -2273,7 +2298,7 @@ static void udp_chr_update_read_handler(CharDriverState
> *chr)
> NetCharDriver *s = chr->opaque;
>
> if (s->tag) {
> - g_source_remove(s->tag);
> + io_remove_watch_poll(s->tag);
> s->tag = 0;
> }
>
> @@ -2286,7 +2311,7 @@ static void udp_chr_close(CharDriverState *chr)
> {
> NetCharDriver *s = chr->opaque;
> if (s->tag) {
> - g_source_remove(s->tag);
> + io_remove_watch_poll(s->tag);
> s->tag = 0;
> }
> if (s->chan) {
> @@ -2520,7 +2545,7 @@ static gboolean tcp_chr_read(GIOChannel *chan,
> GIOCondition cond, void *opaque)
> s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN,
> tcp_chr_accept, chr);
> }
> if (s->tag) {
> - g_source_remove(s->tag);
> + io_remove_watch_poll(s->tag);
> s->tag = 0;
> }
> g_io_channel_unref(s->chan);
> @@ -2635,7 +2660,7 @@ static void tcp_chr_close(CharDriverState *chr)
> TCPCharDriver *s = chr->opaque;
> if (s->fd >= 0) {
> if (s->tag) {
> - g_source_remove(s->tag);
> + io_remove_watch_poll(s->tag);
> s->tag = 0;
> }
> if (s->chan) {
- [Qemu-devel] [PATCH v2 0/4] another round of qemu-char fixes, Paolo Bonzini, 2013/04/19
- [Qemu-devel] [PATCH v2 2/4] qemu-char: simplify pty polling, Paolo Bonzini, 2013/04/19
- [Qemu-devel] [PATCH v2 1/4] qemu-char: use consistent idiom for removing sources, Paolo Bonzini, 2013/04/19
- [Qemu-devel] [PATCH v2 3/4] qemu-char: correct return value from chr_read functions, Paolo Bonzini, 2013/04/19
- [Qemu-devel] [PATCH v2 4/4] qemu-char: do not operate on sources from finalize callbacks, Paolo Bonzini, 2013/04/19
- Re: [Qemu-devel] [PATCH v2 4/4] qemu-char: do not operate on sources from finalize callbacks,
Sander Eikelenboom <=
- Re: [Qemu-devel] [PATCH v2 0/4] another round of qemu-char fixes, Anthony Liguori, 2013/04/22