aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-01-30 15:56:53 +0100
committerMax Kellermann <max@duempel.org>2009-01-30 15:56:53 +0100
commit76b217f71e5e39c0ebc433338f9c08975285561a (patch)
treef13d3c09cb601c72be473f27b2d9d80714ba6678
parentc38dd9e8d84eb7e398627bf6f2f562b2b0c35012 (diff)
downloadmpd-76b217f71e5e39c0ebc433338f9c08975285561a.tar.gz
mpd-76b217f71e5e39c0ebc433338f9c08975285561a.tar.xz
mpd-76b217f71e5e39c0ebc433338f9c08975285561a.zip
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.
-rw-r--r--src/client.c27
1 files 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;
}