kqueue: Multiple fixes and simplifications

- Stop using a custom thread for listening to kqueue(2) events.  Instead
   call kevent(2) in non blocking mode in a monitor callback.  Under the
   hood poll(2) is used to figure out if new events are available.

 - Do not use a socketpair with a custom protocol requiring 2 supplementary
   context switches per event to commicate between multiple threads.  Calling
   kevent(2), in non blocking mode, to add/remove events is fine from any
   context.

 - Add kqueue(2) events without the EV_ONESHOT flag.  This removes a race
   where some notifications were lost because events had to be re-added for
   every new notification.

 - Get rid of the global hash table and its associated lock and races.  Use
   the 'cookie' argument of kevent(2) to pass the associated descriptor when
   registering an event.

 - Fix _kh_file_appeared_cb() by properly passing a monitor instead of a
   source to g_file_monitor_emit_event().

 - Properly refcount sources.

 - Remove a lot of abstraction making it harder to fix the remaining issues.

https://bugzilla.gnome.org/show_bug.cgi?id=739424
This commit is contained in:
Martin Pieuchot
2018-02-20 16:57:00 +00:00
committed by Philip Withnall
parent 46eedd12c0
commit aa39a0557c
16 changed files with 361 additions and 1400 deletions

View File

@@ -23,12 +23,12 @@
#include <glib.h>
#include "kqueue-helper.h"
#include "kqueue-sub.h"
#include "kqueue-missing.h"
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */
void _kh_file_appeared_cb (kqueue_sub *sub);
static gboolean km_scan_missing (gpointer user_data);
static gboolean km_debug_enabled = FALSE;
@@ -38,21 +38,6 @@ static GSList *missing_subs_list = NULL;
G_LOCK_DEFINE_STATIC (missing_lock);
static volatile gboolean scan_missing_running = FALSE;
static on_create_cb file_appeared_callback;
/**
* _km_init:
* @cb: a callback function. It will be called when a watched file
* will appear.
*
* Initialize the kqueue-missing module (optional).
**/
void
_km_init (on_create_cb cb)
{
file_appeared_callback = cb;
}
/**
@@ -83,6 +68,35 @@ _km_add_missing (kqueue_sub *sub)
}
}
/**
* _kh_file_appeared_cb:
* @sub: a #kqueue_sub
*
* A callback function for kqueue-missing subsystem.
*
* Signals that a missing file has finally appeared in the filesystem.
* Emits %G_FILE_MONITOR_EVENT_CREATED.
**/
void
_kh_file_appeared_cb (kqueue_sub *sub)
{
GFile *child;
g_assert (sub != NULL);
g_assert (sub->filename);
if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS))
return;
child = g_file_new_for_path (sub->filename);
g_file_monitor_emit_event (G_FILE_MONITOR (sub->mon),
child,
NULL,
G_FILE_MONITOR_EVENT_CREATED);
g_object_unref (child);
}
/**
* km_scan_missing:
@@ -114,11 +128,10 @@ km_scan_missing (gpointer user_data)
g_assert (sub != NULL);
g_assert (sub->filename != NULL);
if (_kh_start_watching (sub))
if (_kqsub_start_watching (sub))
{
KM_W ("file %s now exists, starting watching", sub->filename);
if (file_appeared_callback)
file_appeared_callback (sub);
_kh_file_appeared_cb (sub);
not_missing = g_slist_prepend (not_missing, head);
}
}