From 76b217f71e5e39c0ebc433338f9c08975285561a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 30 Jan 2009 15:56:53 +0100 Subject: client: check for G_IO_ERR and G_IO_HUP When we do not explicitly catch G_IO_ERR and G_IO_HUP, GLib can go into an infinite loop, because it won't deliver the socket error to MPD. --- src/client.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/client.c b/src/client.c index ceb915d58..423aafeec 100644 --- a/src/client.c +++ b/src/client.c @@ -191,7 +191,8 @@ static void client_init(struct client *client, int fd) /* we prefer to do buffering */ g_io_channel_set_buffered(client->channel, false); - client->source_id = g_io_add_watch(client->channel, G_IO_IN, + client->source_id = g_io_add_watch(client->channel, + G_IO_IN|G_IO_ERR|G_IO_HUP, client_in_event, client); client->lastTime = time(NULL); @@ -498,13 +499,12 @@ static int client_read(struct client *client) } static gboolean -client_out_event(G_GNUC_UNUSED GIOChannel *source, - G_GNUC_UNUSED GIOCondition condition, +client_out_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition, gpointer data); static gboolean client_in_event(G_GNUC_UNUSED GIOChannel *source, - G_GNUC_UNUSED GIOCondition condition, + GIOCondition condition, gpointer data) { struct client *client = data; @@ -512,6 +512,11 @@ client_in_event(G_GNUC_UNUSED GIOChannel *source, assert(!client_is_expired(client)); + if (condition != G_IO_IN) { + client_set_expired(client); + return false; + } + client->lastTime = time(NULL); ret = client_read(client); @@ -533,7 +538,8 @@ client_in_event(G_GNUC_UNUSED GIOChannel *source, if (!g_queue_is_empty(client->deferred_send)) { /* deferred buffers exist: schedule write */ - client->source_id = g_io_add_watch(client->channel, G_IO_OUT, + client->source_id = g_io_add_watch(client->channel, + G_IO_OUT|G_IO_ERR|G_IO_HUP, client_out_event, client); return false; } @@ -543,14 +549,18 @@ client_in_event(G_GNUC_UNUSED GIOChannel *source, } static gboolean -client_out_event(G_GNUC_UNUSED GIOChannel *source, - G_GNUC_UNUSED GIOCondition condition, +client_out_event(G_GNUC_UNUSED GIOChannel *source, GIOCondition condition, gpointer data) { struct client *client = data; assert(!client_is_expired(client)); + if (condition != G_IO_OUT) { + client_set_expired(client); + return false; + } + client_write_deferred(client); if (client_is_expired(client)) { @@ -563,7 +573,8 @@ client_out_event(G_GNUC_UNUSED GIOChannel *source, if (g_queue_is_empty(client->deferred_send)) { /* done sending deferred buffers exist: schedule read */ - client->source_id = g_io_add_watch(client->channel, G_IO_IN, + client->source_id = g_io_add_watch(client->channel, + G_IO_IN|G_IO_ERR|G_IO_HUP, client_in_event, client); return false; } -- cgit v1.2.3