It was originally created by qio_channel_add_watch() so it's always assigning the task to main context. Now we use the new API called qio_channel_add_watch_full() so that we get the GSource handle rather than the tag ID.
Meanwhile, caching the gsource in SocketChardev.telnet_source so that we can also do dynamic context switch when update read handlers. Signed-off-by: Peter Xu <pet...@redhat.com> --- chardev/char-socket.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index 8f0935cd15..a16d894c40 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -59,6 +59,7 @@ typedef struct { bool is_listen; bool is_telnet; bool is_tn3270; + GSource *telnet_source; GSource *reconnect_timer; int64_t reconnect_time; @@ -69,6 +70,7 @@ typedef struct { OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET) static gboolean socket_reconnect_timeout(gpointer opaque); +static void tcp_chr_telnet_init(Chardev *chr); static void tcp_chr_reconn_timer_cancel(SocketChardev *s) { @@ -555,6 +557,15 @@ static void tcp_chr_connect(void *opaque) qemu_chr_be_event(chr, CHR_EVENT_OPENED); } +static void tcp_chr_telnet_destroy(SocketChardev *s) +{ + if (s->telnet_source) { + g_source_destroy(s->telnet_source); + g_source_unref(s->telnet_source); + s->telnet_source = NULL; + } +} + static void tcp_chr_update_read_handler(Chardev *chr) { SocketChardev *s = SOCKET_CHARDEV(chr); @@ -568,6 +579,11 @@ static void tcp_chr_update_read_handler(Chardev *chr) qio_net_listener_set_context(s->listener, chr->gcontext); } + if (s->telnet_source) { + tcp_chr_telnet_destroy(s); + tcp_chr_telnet_init(CHARDEV(s)); + } + if (!s->connected) { return; } @@ -592,6 +608,7 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, gpointer user_data) { TCPChardevTelnetInit *init = user_data; + SocketChardev *s = SOCKET_CHARDEV(init->chr); ssize_t ret; ret = qio_channel_write(ioc, init->buf, init->buflen, NULL); @@ -616,6 +633,8 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc, end: g_free(init); + g_source_unref(s->telnet_source); + s->telnet_source = NULL; return G_SOURCE_REMOVE; } @@ -655,10 +674,10 @@ static void tcp_chr_telnet_init(Chardev *chr) #undef IACSET - qio_channel_add_watch( - s->ioc, G_IO_OUT, - tcp_chr_telnet_init_io, - init, NULL); + s->telnet_source = qio_channel_add_watch_full(s->ioc, G_IO_OUT, + tcp_chr_telnet_init_io, + init, NULL, + chr->gcontext); } @@ -831,6 +850,7 @@ static void char_socket_finalize(Object *obj) tcp_chr_free_connection(chr); tcp_chr_reconn_timer_cancel(s); qapi_free_SocketAddress(s->addr); + tcp_chr_telnet_destroy(s); if (s->listener) { qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL); object_unref(OBJECT(s->listener)); -- 2.14.3