Move the GSource attach out to the generic watch code, and avoid blocking reads
authorDana Jansens <danakj@orodu.net>
Mon, 24 Jan 2011 21:57:37 +0000 (16:57 -0500)
committerDana Jansens <danakj@orodu.net>
Sun, 16 Oct 2011 22:54:04 +0000 (18:54 -0400)
GLib seems to call the read function sometimes even tho the PollFD's revents
field is empty.  So don't read from the fd if this happens.

obt/watch.c
obt/watch_inotify.c

index 6e1971ac44339a9fb841cf081365322b80fcf322..487655cd792c8ee4a64376052c999ace8be2a88d 100644 (file)
@@ -88,6 +88,8 @@ ObtWatch* obt_watch_new()
         w->targets_by_path = g_hash_table_new_full(
             g_str_hash, g_str_equal, NULL, (GDestroyNotify)target_free);
         w->source = source;
+
+        g_source_attach(source, NULL);
     }
     return w;
 }
index f9a5649afa7a350ebd11bc4c0576ea11fe8c36b9..2aff0e394e8e89e2ee92783a85e515ba38fc0010 100644 (file)
@@ -121,7 +121,6 @@ GSource* watch_sys_create_source(ObtWatchNotifyFunc notify)
             g_str_hash, g_str_equal, NULL, (GDestroyNotify)target_free);
         ino_source->pfd = (GPollFD){ fd, G_IO_IN, G_IO_IN };
         g_source_add_poll(source, &ino_source->pfd);
-        g_source_attach(source, NULL);
     }
     return source;
 }
@@ -158,7 +157,9 @@ static gboolean source_read(GSource *source, GSourceFunc cb, gpointer data)
     state = READING_EVENT;
     len = event_len = name_len = 0;
 
-    while (TRUE) {
+    /* sometimes we can end up here even tho no events have been reported by
+       the kernel.  blame glib?  but we'll block if we read in that case. */
+    while (ino_source->pfd.revents) {
         if (pos == len || !len || event_len) {
             /* refill the buffer */
 
@@ -169,10 +170,16 @@ static gboolean source_read(GSource *source, GSourceFunc cb, gpointer data)
 
             len = read(ino_source->pfd.fd, &buffer[pos], BUF_LEN-pos);
 
-            if (len < 0 && errno != EINTR) {
-                gchar *s = strerror(errno);
-                g_warning("Failed to read from inotify: %s", s);
-                return FALSE; /* won't read any more */
+            if (len < 0) {
+                if (errno != EINTR) {
+                    gchar *s = strerror(errno);
+                    g_warning("Failed to read from inotify: %s", s);
+                    return FALSE; /* won't read any more */
+                }
+                else {
+                    g_warning("Interrupted reading from inotify");
+                    return TRUE;
+                }
             }
             if (len == 0) {
                 g_debug("Done reading from inotify");