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,16 +23,31 @@
#ifndef __KQUEUE_HELPER_H
#define __KQUEUE_HELPER_H
#include "kqueue-sub.h"
#include <gio/glocalfilemonitor.h>
#include <gio/gfilemonitor.h>
gboolean _kh_startup (void);
gboolean _kh_add_sub (kqueue_sub *sub);
gboolean _kh_cancel_sub (kqueue_sub *sub);
#include "dep-list.h"
gboolean _kh_start_watching (kqueue_sub *sub);
/**
* kqueue_sub:
* @filename: a name of the file to monitor
* @fd: the associated file descriptor (used by kqueue)
*
* Represents a subscription on a file or directory.
*/
typedef struct
{
GLocalFileMonitor *mon;
GFileMonitorSource *source;
gchar* filename;
int fd;
dep_list* deps;
int is_dir;
} kqueue_sub;
void _kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source);
gboolean _kqsub_start_watching (kqueue_sub *sub);
void _kh_dir_diff (kqueue_sub *sub);
void _km_add_missing (kqueue_sub *sub);
void _km_remove (kqueue_sub *sub);
#endif /* __KQUEUE_HELPER_H */