diff options
author | iain <iain@linux.intel.com> | 2011-12-06 13:00:31 +0000 |
---|---|---|
committer | iain <iain@linux.intel.com> | 2011-12-06 13:00:31 +0000 |
commit | 754ac3bdf53d7fc3f9383f0e009c71f2b2e26381 (patch) | |
tree | 2cf302f166f7b4e867975fd6dc0ea1b7061bab32 | |
parent | 8078296aeedd7bd823e63619d7d056c01679e9de (diff) |
Only open TTY devices once
TTY devices were accidentally being opened twice but only closed once. This
meant that when a device file was removed, but then replaced, a file descriptor for the old device was cached somewhere in the deep bowels of the system and
this dead file descriptor was being returned when Gypsy attempted to open the
new device, causing I/O errors when trying to read from it. Which in turn
caused some lovely CPU pegging as Gypsy would just enter a busy loop constantly
trying to read from the dead descriptor.
In short, everyone's a winner!
-rw-r--r-- | src/gypsy-client.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/src/gypsy-client.c b/src/gypsy-client.c index 8b1763b..63cad6d 100644 --- a/src/gypsy-client.c +++ b/src/gypsy-client.c @@ -220,21 +220,23 @@ shutdown_connection (GypsyClient *client) priv->input_id = 0; } - if (priv->fd > 0) { - close (priv->fd); - priv->fd = -1; - } - if (priv->channel) { + g_io_channel_shutdown (priv->channel, TRUE, NULL); g_io_channel_unref (priv->channel); priv->channel = NULL; } if (priv->debug_log) { + g_io_channel_shutdown (priv->channel, TRUE, NULL); g_io_channel_unref (priv->debug_log); priv->debug_log = NULL; } + if (priv->fd > 0) { + close (priv->fd); + priv->fd = -1; + } + if (priv->parser) { g_object_unref (priv->parser); priv->parser = NULL; @@ -278,6 +280,7 @@ gps_channel_input (GIOChannel *channel, GIOStatus status; char *buf; gsize chars_left_in_buffer, chars_read; + GError *error = NULL; priv = GET_PRIVATE (userdata); @@ -286,8 +289,7 @@ gps_channel_input (GIOChannel *channel, (char *) buf, chars_left_in_buffer, &chars_read, - NULL); - + &error); if (priv->debug_log) { g_io_channel_write_chars (priv->debug_log, buf, chars_read, NULL, NULL); @@ -296,7 +298,8 @@ gps_channel_input (GIOChannel *channel, if (status == G_IO_STATUS_NORMAL) { gypsy_parser_received_data (priv->parser, chars_read, NULL); } else { - GYPSY_NOTE (CLIENT, "Read error: %s", g_strerror (errno)); + GYPSY_NOTE (CLIENT, "Read error on channel %p %d: %s (%s)", priv->channel, status, error->message, g_strerror (errno)); + g_error_free (error); } return TRUE; @@ -587,7 +590,7 @@ gypsy_client_start (GypsyClient *client, } else { priv->type = GYPSY_DEVICE_TYPE_FIFO; } - priv->fd = open (priv->device_path, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (priv->fd == -1) { g_warning ("Error opening device %s: %s", priv->device_path, g_strerror (errno)); g_set_error (error, GYPSY_ERROR, errno, g_strerror (errno)); @@ -642,6 +645,7 @@ gypsy_client_start (GypsyClient *client, /* Set up the IO Channel */ priv->channel = g_io_channel_unix_new (priv->fd); + GYPSY_NOTE (CLIENT, "Created new channel: %p", priv->channel); status = g_io_channel_set_flags (priv->channel, G_IO_FLAG_NONBLOCK | G_IO_FLAG_IS_READABLE | G_IO_FLAG_IS_WRITEABLE, |