qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

chardev: fix incorrect unref of source

glib reported error when pty chardev used:

$ ./qemu-system-x86_64 -chardev pty,id=foo -device isa-serial,chardev=foo
qemu-system-x86_64: -chardev pty,id=foo: char device redirected to /dev/pts/2 (label foo)
(qemu-system-x86_64:27885): GLib-CRITICAL **: g_source_unref: assertion 'source != NULL' failed
(qemu-system-x86_64:27885): GLib-CRITICAL **: g_source_unref: assertion 'source != NULL' failed

This patch fixes that.

Fixes: 2c716ba150 ("chardev: introduce qemu_chr_timeout_add_ms()")
CC: Paolo Bonzini <pbonzini@redhat.com>
Reported-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20180118052049.31119-1-peterx@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Peter Xu and committed by
Paolo Bonzini
4e4b5734 c6caae55

+21 -17
+21 -17
chardev/char-pty.c
··· 51 51 static void pty_chr_update_read_handler_locked(Chardev *chr); 52 52 static void pty_chr_state(Chardev *chr, int connected); 53 53 54 + static void pty_chr_timer_cancel(PtyChardev *s) 55 + { 56 + if (s->timer_src) { 57 + g_source_destroy(s->timer_src); 58 + g_source_unref(s->timer_src); 59 + s->timer_src = NULL; 60 + } 61 + } 62 + 63 + static void pty_chr_open_src_cancel(PtyChardev *s) 64 + { 65 + if (s->open_source) { 66 + g_source_destroy(s->open_source); 67 + g_source_unref(s->open_source); 68 + s->open_source = NULL; 69 + } 70 + } 71 + 54 72 static gboolean pty_chr_timer(gpointer opaque) 55 73 { 56 74 struct Chardev *chr = CHARDEV(opaque); 57 75 PtyChardev *s = PTY_CHARDEV(opaque); 58 76 59 77 qemu_mutex_lock(&chr->chr_write_lock); 60 - s->timer_src = NULL; 61 - g_source_unref(s->open_source); 62 - s->open_source = NULL; 78 + pty_chr_timer_cancel(s); 79 + pty_chr_open_src_cancel(s); 63 80 if (!s->connected) { 64 81 /* Next poll ... */ 65 82 pty_chr_update_read_handler_locked(chr); 66 83 } 67 84 qemu_mutex_unlock(&chr->chr_write_lock); 68 85 return FALSE; 69 - } 70 - 71 - static void pty_chr_timer_cancel(PtyChardev *s) 72 - { 73 - if (s->timer_src) { 74 - g_source_destroy(s->timer_src); 75 - g_source_unref(s->timer_src); 76 - s->timer_src = NULL; 77 - } 78 86 } 79 87 80 88 /* Called with chr_write_lock held. */ ··· 195 203 PtyChardev *s = PTY_CHARDEV(chr); 196 204 197 205 if (!connected) { 198 - if (s->open_source) { 199 - g_source_destroy(s->open_source); 200 - g_source_unref(s->open_source); 201 - s->open_source = NULL; 202 - } 206 + pty_chr_open_src_cancel(s); 203 207 remove_fd_in_watch(chr); 204 208 s->connected = 0; 205 209 /* (re-)connect poll interval for idle guests: once per second.