Revision 2b316774
b/qemu-char.c | ||
---|---|---|
643 | 643 |
|
644 | 644 |
static void io_watch_poll_finalize(GSource *source) |
645 | 645 |
{ |
646 |
/* Due to a glib bug, removing the last reference to a source |
|
647 |
* inside a finalize callback causes recursive locking (and a |
|
648 |
* deadlock). This is not a problem inside other callbacks, |
|
649 |
* including dispatch callbacks, so we call io_remove_watch_poll |
|
650 |
* to remove this source. At this point, iwp->src must |
|
651 |
* be NULL, or we would leak it. |
|
652 |
* |
|
653 |
* This would be solved much more elegantly by child sources, |
|
654 |
* but we support older glib versions that do not have them. |
|
655 |
*/ |
|
646 | 656 |
IOWatchPoll *iwp = io_watch_poll_from_source(source); |
647 |
if (iwp->src) { |
|
648 |
g_source_destroy(iwp->src); |
|
649 |
g_source_unref(iwp->src); |
|
650 |
iwp->src = NULL; |
|
651 |
} |
|
657 |
assert(iwp->src == NULL); |
|
652 | 658 |
} |
653 | 659 |
|
654 | 660 |
static GSourceFuncs io_watch_poll_funcs = { |
... | ... | |
679 | 685 |
return tag; |
680 | 686 |
} |
681 | 687 |
|
688 |
static void io_remove_watch_poll(guint tag) |
|
689 |
{ |
|
690 |
GSource *source; |
|
691 |
IOWatchPoll *iwp; |
|
692 |
|
|
693 |
g_return_if_fail (tag > 0); |
|
694 |
|
|
695 |
source = g_main_context_find_source_by_id(NULL, tag); |
|
696 |
g_return_if_fail (source != NULL); |
|
697 |
|
|
698 |
iwp = io_watch_poll_from_source(source); |
|
699 |
if (iwp->src) { |
|
700 |
g_source_destroy(iwp->src); |
|
701 |
g_source_unref(iwp->src); |
|
702 |
iwp->src = NULL; |
|
703 |
} |
|
704 |
g_source_destroy(&iwp->parent); |
|
705 |
} |
|
706 |
|
|
682 | 707 |
#ifndef _WIN32 |
683 | 708 |
static GIOChannel *io_channel_from_fd(int fd) |
684 | 709 |
{ |
... | ... | |
788 | 813 |
len, &bytes_read, NULL); |
789 | 814 |
if (status == G_IO_STATUS_EOF) { |
790 | 815 |
if (s->fd_in_tag) { |
791 |
g_source_remove(s->fd_in_tag);
|
|
816 |
io_remove_watch_poll(s->fd_in_tag);
|
|
792 | 817 |
s->fd_in_tag = 0; |
793 | 818 |
} |
794 | 819 |
qemu_chr_be_event(chr, CHR_EVENT_CLOSED); |
... | ... | |
821 | 846 |
FDCharDriver *s = chr->opaque; |
822 | 847 |
|
823 | 848 |
if (s->fd_in_tag) { |
824 |
g_source_remove(s->fd_in_tag);
|
|
849 |
io_remove_watch_poll(s->fd_in_tag);
|
|
825 | 850 |
s->fd_in_tag = 0; |
826 | 851 |
} |
827 | 852 |
|
... | ... | |
835 | 860 |
FDCharDriver *s = chr->opaque; |
836 | 861 |
|
837 | 862 |
if (s->fd_in_tag) { |
838 |
g_source_remove(s->fd_in_tag);
|
|
863 |
io_remove_watch_poll(s->fd_in_tag);
|
|
839 | 864 |
s->fd_in_tag = 0; |
840 | 865 |
} |
841 | 866 |
|
... | ... | |
1145 | 1170 |
|
1146 | 1171 |
if (!connected) { |
1147 | 1172 |
if (s->fd_tag) { |
1148 |
g_source_remove(s->fd_tag);
|
|
1173 |
io_remove_watch_poll(s->fd_tag);
|
|
1149 | 1174 |
s->fd_tag = 0; |
1150 | 1175 |
} |
1151 | 1176 |
s->connected = 0; |
... | ... | |
1173 | 1198 |
int fd; |
1174 | 1199 |
|
1175 | 1200 |
if (s->fd_tag) { |
1176 |
g_source_remove(s->fd_tag);
|
|
1201 |
io_remove_watch_poll(s->fd_tag);
|
|
1177 | 1202 |
s->fd_tag = 0; |
1178 | 1203 |
} |
1179 | 1204 |
fd = g_io_channel_unix_get_fd(s->fd); |
... | ... | |
2252 | 2277 |
s->bufptr = s->bufcnt; |
2253 | 2278 |
if (status != G_IO_STATUS_NORMAL) { |
2254 | 2279 |
if (s->tag) { |
2255 |
g_source_remove(s->tag);
|
|
2280 |
io_remove_watch_poll(s->tag);
|
|
2256 | 2281 |
s->tag = 0; |
2257 | 2282 |
} |
2258 | 2283 |
return FALSE; |
... | ... | |
2273 | 2298 |
NetCharDriver *s = chr->opaque; |
2274 | 2299 |
|
2275 | 2300 |
if (s->tag) { |
2276 |
g_source_remove(s->tag);
|
|
2301 |
io_remove_watch_poll(s->tag);
|
|
2277 | 2302 |
s->tag = 0; |
2278 | 2303 |
} |
2279 | 2304 |
|
... | ... | |
2286 | 2311 |
{ |
2287 | 2312 |
NetCharDriver *s = chr->opaque; |
2288 | 2313 |
if (s->tag) { |
2289 |
g_source_remove(s->tag);
|
|
2314 |
io_remove_watch_poll(s->tag);
|
|
2290 | 2315 |
s->tag = 0; |
2291 | 2316 |
} |
2292 | 2317 |
if (s->chan) { |
... | ... | |
2520 | 2545 |
s->listen_tag = g_io_add_watch(s->listen_chan, G_IO_IN, tcp_chr_accept, chr); |
2521 | 2546 |
} |
2522 | 2547 |
if (s->tag) { |
2523 |
g_source_remove(s->tag);
|
|
2548 |
io_remove_watch_poll(s->tag);
|
|
2524 | 2549 |
s->tag = 0; |
2525 | 2550 |
} |
2526 | 2551 |
g_io_channel_unref(s->chan); |
... | ... | |
2635 | 2660 |
TCPCharDriver *s = chr->opaque; |
2636 | 2661 |
if (s->fd >= 0) { |
2637 | 2662 |
if (s->tag) { |
2638 |
g_source_remove(s->tag);
|
|
2663 |
io_remove_watch_poll(s->tag);
|
|
2639 | 2664 |
s->tag = 0; |
2640 | 2665 |
} |
2641 | 2666 |
if (s->chan) { |
Also available in: Unified diff