inotify: don't assume mainloop is running

GFileMonitor takes great care to sample the thread-default main context
at the time that it is created in order that events can be dispatched to
the correct thread when they come in.

The inotify GFileMonitor implementation uses a global file descriptor
shared between all watches.  It has to poll this file descriptor from
somewhere so it arbitrarily picks the default main context.

The problem with that is that the user might not be running it.

Let's use the GLib worker thread for this instead.  It's guaranteed to
be running if you need it, and this is exactly the sort of problem it
was meant to solve.

https://bugzilla.gnome.org/show_bug.cgi?id=704873
This commit is contained in:
Ryan Lortie 2013-07-25 10:28:42 -04:00 committed by Matthias Clasen
parent 5843582604
commit abbb225738
2 changed files with 23 additions and 5 deletions

View File

@ -31,6 +31,8 @@
#include "inotify-kernel.h"
#include <sys/inotify.h>
#include "glib-private.h"
/* Timings for pairing MOVED_TO / MOVED_FROM events */
#define PROCESS_EVENTS_TIME 1000 /* 1000 milliseconds (1 hz) */
#define DEFAULT_HOLD_UNTIL_TIME 0 /* 0 millisecond */
@ -116,6 +118,7 @@ ik_source_check (GSource *source)
if (pending_count < MAX_PENDING_COUNT)
{
GSource *timeout_source;
unsigned int pending;
if (ioctl (inotify_instance_fd, FIONREAD, &pending) == -1)
@ -146,8 +149,12 @@ ik_source_check (GSource *source)
ik_poll_fd_enabled = FALSE;
/* Set a timeout to re-add the PollFD to the source */
g_source_ref (source);
g_timeout_add (TIMEOUT_MILLISECONDS, ik_source_timeout, source);
timeout_source = g_timeout_source_new (TIMEOUT_MILLISECONDS);
g_source_set_callback (timeout_source, ik_source_timeout, source, NULL);
g_source_attach (timeout_source, glib__private__ ()->g_get_worker_context ());
g_source_unref (timeout_source);
return FALSE;
}
@ -211,7 +218,7 @@ gboolean _ik_startup (void (*cb)(ik_event_t *event))
g_source_set_name (source, "GIO Inotify");
g_source_add_poll (source, &ik_poll_fd);
g_source_set_callback (source, ik_read_callback, NULL, NULL);
g_source_attach (source, NULL);
g_source_attach (source, glib__private__ ()->g_get_worker_context ());
g_source_unref (source);
cookie_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
@ -359,8 +366,13 @@ ik_read_callback (gpointer user_data)
/* If the event process callback is off, turn it back on */
if (!process_eq_running && events)
{
GSource *timeout_source;
process_eq_running = TRUE;
g_timeout_add (PROCESS_EVENTS_TIME, ik_process_eq_callback, NULL);
timeout_source = g_timeout_source_new (PROCESS_EVENTS_TIME);
g_source_set_callback (timeout_source, ik_process_eq_callback, NULL, NULL);
g_source_attach (timeout_source, glib__private__ ()->g_get_worker_context ());
g_source_unref (timeout_source);
}
G_UNLOCK (inotify_lock);

View File

@ -27,6 +27,7 @@
#include <glib.h>
#include "inotify-missing.h"
#include "inotify-path.h"
#include "glib-private.h"
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
@ -70,8 +71,13 @@ _im_add (inotify_sub *sub)
/* If the timeout is turned off, we turn it back on */
if (!scan_missing_running)
{
GSource *source;
scan_missing_running = TRUE;
g_timeout_add_seconds (SCAN_MISSING_TIME, im_scan_missing, NULL);
source = g_timeout_source_new_seconds (SCAN_MISSING_TIME);
g_source_set_callback (source, im_scan_missing, NULL, NULL);
g_source_attach (source, glib__private__ ()->g_get_worker_context ());
g_source_unref (source);
}
}