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