summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriain <iain@linux.intel.com>2011-12-06 13:00:31 +0000
committeriain <iain@linux.intel.com>2011-12-06 13:00:31 +0000
commit754ac3bdf53d7fc3f9383f0e009c71f2b2e26381 (patch)
tree2cf302f166f7b4e867975fd6dc0ea1b7061bab32
parent8078296aeedd7bd823e63619d7d056c01679e9de (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.c22
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,