Line 0
Link Here
|
|
|
1 |
commit e305fe971e4647d971428a772b7290b9c308a96f |
2 |
Author: Steven McDonald <steven@steven-mcdonald.id.au> |
3 |
Date: Sun Feb 12 11:02:55 2017 +1100 |
4 |
|
5 |
gio: Always purge kqueue subs from missing list |
6 |
|
7 |
Previously, _kh_cancel_sub assumed that it only needed to call |
8 |
_km_remove if sub did not exist in subs_hash_table. This is erroneous |
9 |
because the complementary operation, _km_add_missing, can be called |
10 |
from process_kqueue_notifications, in which context sub can *only* have |
11 |
come from subs_hash_table. |
12 |
|
13 |
Since _km_remove is implemented using g_slist_remove, which is |
14 |
documented to be a noop if the list does not contain the element to be |
15 |
removed, it is safe to call _km_remove unconditionally here. |
16 |
|
17 |
https://bugzilla.gnome.org/show_bug.cgi?id=778515 |
18 |
|
19 |
diff --git gio/kqueue/kqueue-helper.c gio/kqueue/kqueue-helper.c |
20 |
index 4671396a2..d4e66cd4d 100644 |
21 |
--- gio/kqueue/kqueue-helper.c |
22 |
+++ gio/kqueue/kqueue-helper.c |
23 |
@@ -498,22 +498,17 @@ _kh_add_sub (kqueue_sub *sub) |
24 |
gboolean |
25 |
_kh_cancel_sub (kqueue_sub *sub) |
26 |
{ |
27 |
- gboolean missing = FALSE; |
28 |
+ gboolean removed = FALSE; |
29 |
g_assert (kqueue_socket_pair[0] != -1); |
30 |
g_assert (sub != NULL); |
31 |
|
32 |
+ _km_remove (sub); |
33 |
+ |
34 |
G_LOCK (hash_lock); |
35 |
- missing = !g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd)); |
36 |
+ removed = g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd)); |
37 |
G_UNLOCK (hash_lock); |
38 |
|
39 |
- if (missing) |
40 |
- { |
41 |
- /* If there were no fd for this subscription, file is still |
42 |
- * missing. */ |
43 |
- KH_W ("Removing subscription from missing"); |
44 |
- _km_remove (sub); |
45 |
- } |
46 |
- else |
47 |
+ if (removed) |
48 |
{ |
49 |
/* fd will be closed in the kqueue thread */ |
50 |
_kqueue_thread_remove_fd (sub->fd); |
51 |
commit 76072a2dde4a4acc8be8d3c47efbc6811ebe0c1e |
52 |
Author: Philip Withnall <withnall@endlessm.com> |
53 |
Date: Fri Nov 10 15:10:26 2017 +0000 |
54 |
|
55 |
kqueue: Fix invalid emission of G_FILE_MONITOR_EVENT_MOVED event |
56 |
|
57 |
That event is deprecated, and the kqueue backend can’t provide enough |
58 |
information to go alongside the event (i.e. the name of the new file). |
59 |
Use G_FILE_MONITOR_EVENT_DELETED instead. |
60 |
|
61 |
Quite disappointed in the kqueue documentation for this: I cannot find a |
62 |
single piece of documentation or example about how NOTE_RENAME is |
63 |
supposed to communicate the new name of the file. |
64 |
|
65 |
If it turns out that this is possible, the code can be amended again in |
66 |
future. At least now it doesn’t abort. |
67 |
|
68 |
Signed-off-by: Philip Withnall <withnall@endlessm.com> |
69 |
|
70 |
https://bugzilla.gnome.org/show_bug.cgi?id=776147 |
71 |
|
72 |
diff --git gio/kqueue/kqueue-helper.c gio/kqueue/kqueue-helper.c |
73 |
index d4e66cd4d..e7d583c8b 100644 |
74 |
--- gio/kqueue/kqueue-helper.c |
75 |
+++ gio/kqueue/kqueue-helper.c |
76 |
@@ -97,8 +97,10 @@ convert_kqueue_events_to_gio (uint32_t flags, gboolean *done) |
77 |
} |
78 |
if (flags & NOTE_RENAME) |
79 |
{ |
80 |
+ /* Since there’s apparently no way to get the new name of the file out of |
81 |
+ * kqueue(), all we can do is say that this one has been deleted. */ |
82 |
*done = TRUE; |
83 |
- return G_FILE_MONITOR_EVENT_MOVED; |
84 |
+ return G_FILE_MONITOR_EVENT_DELETED; |
85 |
} |
86 |
if (flags & NOTE_REVOKE) |
87 |
{ |
88 |
commit aa39a0557c679fc345b0ba72a87c33152eb8ebcd |
89 |
Author: Martin Pieuchot <mpi@openbsd.org> |
90 |
Date: Tue Feb 20 16:57:00 2018 +0000 |
91 |
|
92 |
kqueue: Multiple fixes and simplifications |
93 |
|
94 |
- Stop using a custom thread for listening to kqueue(2) events. Instead |
95 |
call kevent(2) in non blocking mode in a monitor callback. Under the |
96 |
hood poll(2) is used to figure out if new events are available. |
97 |
|
98 |
- Do not use a socketpair with a custom protocol requiring 2 supplementary |
99 |
context switches per event to commicate between multiple threads. Calling |
100 |
kevent(2), in non blocking mode, to add/remove events is fine from any |
101 |
context. |
102 |
|
103 |
- Add kqueue(2) events without the EV_ONESHOT flag. This removes a race |
104 |
where some notifications were lost because events had to be re-added for |
105 |
every new notification. |
106 |
|
107 |
- Get rid of the global hash table and its associated lock and races. Use |
108 |
the 'cookie' argument of kevent(2) to pass the associated descriptor when |
109 |
registering an event. |
110 |
|
111 |
- Fix _kh_file_appeared_cb() by properly passing a monitor instead of a |
112 |
source to g_file_monitor_emit_event(). |
113 |
|
114 |
- Properly refcount sources. |
115 |
|
116 |
- Remove a lot of abstraction making it harder to fix the remaining issues. |
117 |
|
118 |
https://bugzilla.gnome.org/show_bug.cgi?id=739424 |
119 |
|
120 |
diff --git gio/kqueue/Makefile.am gio/kqueue/Makefile.am |
121 |
index d5657d7e4..24e9724e5 100644 |
122 |
--- gio/kqueue/Makefile.am |
123 |
+++ gio/kqueue/Makefile.am |
124 |
@@ -4,19 +4,9 @@ noinst_LTLIBRARIES += libkqueue.la |
125 |
|
126 |
libkqueue_la_SOURCES = \ |
127 |
gkqueuefilemonitor.c \ |
128 |
- gkqueuefilemonitor.h \ |
129 |
kqueue-helper.c \ |
130 |
kqueue-helper.h \ |
131 |
- kqueue-thread.c \ |
132 |
- kqueue-thread.h \ |
133 |
- kqueue-sub.c \ |
134 |
- kqueue-sub.h \ |
135 |
kqueue-missing.c \ |
136 |
- kqueue-missing.h \ |
137 |
- kqueue-utils.c \ |
138 |
- kqueue-utils.h \ |
139 |
- kqueue-exclusions.c \ |
140 |
- kqueue-exclusions.h \ |
141 |
dep-list.c \ |
142 |
dep-list.h \ |
143 |
$(NULL) |
144 |
diff --git gio/kqueue/gkqueuefilemonitor.c gio/kqueue/gkqueuefilemonitor.c |
145 |
index 78b749637..deed8b1e1 100644 |
146 |
--- gio/kqueue/gkqueuefilemonitor.c |
147 |
+++ gio/kqueue/gkqueuefilemonitor.c |
148 |
@@ -22,33 +22,73 @@ |
149 |
|
150 |
#include "config.h" |
151 |
|
152 |
-#include "gkqueuefilemonitor.h" |
153 |
-#include "kqueue-helper.h" |
154 |
-#include "kqueue-exclusions.h" |
155 |
+#include <sys/types.h> |
156 |
+#include <sys/event.h> |
157 |
+#include <sys/time.h> |
158 |
+#include <sys/socket.h> |
159 |
+#include <sys/stat.h> |
160 |
+ |
161 |
+#include <errno.h> |
162 |
+#include <fcntl.h> |
163 |
+#include <string.h> |
164 |
+ |
165 |
+#include <glib-object.h> |
166 |
+#include <gio/gfilemonitor.h> |
167 |
+#include <gio/glocalfilemonitor.h> |
168 |
+#include <gio/giomodule.h> |
169 |
#include <gio/gpollfilemonitor.h> |
170 |
#include <gio/gfile.h> |
171 |
-#include <gio/giomodule.h> |
172 |
+#include <glib-unix.h> |
173 |
+#include "glib-private.h" |
174 |
+ |
175 |
+#include "kqueue-helper.h" |
176 |
+#include "dep-list.h" |
177 |
+ |
178 |
+G_LOCK_DEFINE_STATIC (kq_lock); |
179 |
+static GSource *kq_source; |
180 |
+static int kq_queue = -1; |
181 |
+ |
182 |
+#define G_TYPE_KQUEUE_FILE_MONITOR (g_kqueue_file_monitor_get_type ()) |
183 |
+#define G_KQUEUE_FILE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ |
184 |
+ G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor)) |
185 |
|
186 |
+typedef GLocalFileMonitorClass GKqueueFileMonitorClass; |
187 |
|
188 |
-struct _GKqueueFileMonitor |
189 |
+typedef struct |
190 |
{ |
191 |
GLocalFileMonitor parent_instance; |
192 |
|
193 |
kqueue_sub *sub; |
194 |
- |
195 |
+#ifndef O_EVTONLY |
196 |
GFileMonitor *fallback; |
197 |
GFile *fbfile; |
198 |
-}; |
199 |
+#endif |
200 |
+} GKqueueFileMonitor; |
201 |
+ |
202 |
+GType g_kqueue_file_monitor_get_type (void); |
203 |
+G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, |
204 |
+ g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, |
205 |
+ g_define_type_id, |
206 |
+ "kqueue", |
207 |
+ 20)) |
208 |
+ |
209 |
+#ifndef O_EVTONLY |
210 |
+#define O_KQFLAG O_RDONLY |
211 |
+#else |
212 |
+#define O_KQFLAG O_EVTONLY |
213 |
+#endif |
214 |
+ |
215 |
+#define NOTE_ALL (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME) |
216 |
|
217 |
static gboolean g_kqueue_file_monitor_cancel (GFileMonitor* monitor); |
218 |
+static gboolean g_kqueue_file_monitor_is_supported (void); |
219 |
|
220 |
-G_DEFINE_TYPE_WITH_CODE (GKqueueFileMonitor, g_kqueue_file_monitor, G_TYPE_LOCAL_FILE_MONITOR, |
221 |
- g_io_extension_point_implement (G_LOCAL_FILE_MONITOR_EXTENSION_POINT_NAME, |
222 |
- g_define_type_id, |
223 |
- "kqueue", |
224 |
- 20)) |
225 |
+static kqueue_sub *_kqsub_new (const gchar *, GLocalFileMonitor *, GFileMonitorSource *); |
226 |
+static void _kqsub_free (kqueue_sub *); |
227 |
+static gboolean _kqsub_cancel (kqueue_sub *); |
228 |
|
229 |
|
230 |
+#ifndef O_EVTONLY |
231 |
static void |
232 |
_fallback_callback (GFileMonitor *unused, |
233 |
GFile *first, |
234 |
@@ -57,21 +97,41 @@ _fallback_callback (GFileMonitor *unused, |
235 |
gpointer udata) |
236 |
{ |
237 |
GKqueueFileMonitor *kq_mon = G_KQUEUE_FILE_MONITOR (udata); |
238 |
- GFileMonitor *mon = G_FILE_MONITOR (kq_mon); |
239 |
- g_assert (kq_mon != NULL); |
240 |
- g_assert (mon != NULL); |
241 |
- (void) unused; |
242 |
|
243 |
- if (event == G_FILE_MONITOR_EVENT_CHANGED) |
244 |
- { |
245 |
- GLocalFileMonitor *local_monitor = G_LOCAL_FILE_MONITOR (kq_mon); |
246 |
- |
247 |
- _kh_dir_diff (kq_mon->sub, local_monitor->source); |
248 |
- } |
249 |
- else |
250 |
- g_file_monitor_emit_event (mon, first, second, event); |
251 |
+ g_file_monitor_emit_event (G_FILE_MONITOR (kq_mon), first, second, event); |
252 |
} |
253 |
|
254 |
+/* |
255 |
+ * _ke_is_excluded: |
256 |
+ * @full_path - a path to file to check. |
257 |
+ * |
258 |
+ * Returns: TRUE if the file should be excluded from the kqueue-powered |
259 |
+ * monitoring, FALSE otherwise. |
260 |
+ **/ |
261 |
+gboolean |
262 |
+_ke_is_excluded (const char *full_path) |
263 |
+{ |
264 |
+ GFile *f = NULL; |
265 |
+ GMount *mount = NULL; |
266 |
+ |
267 |
+ f = g_file_new_for_path (full_path); |
268 |
+ |
269 |
+ if (f != NULL) { |
270 |
+ mount = g_file_find_enclosing_mount (f, NULL, NULL); |
271 |
+ g_object_unref (f); |
272 |
+ } |
273 |
+ |
274 |
+ if ((mount != NULL && (g_mount_can_unmount (mount))) || g_str_has_prefix (full_path, "/mnt/")) |
275 |
+ { |
276 |
+ g_warning ("Excluding %s from kernel notification, falling back to poll", full_path); |
277 |
+ if (mount) |
278 |
+ g_object_unref (mount); |
279 |
+ return TRUE; |
280 |
+ } |
281 |
+ |
282 |
+ return FALSE; |
283 |
+} |
284 |
+#endif /* !O_EVTONLY */ |
285 |
|
286 |
static void |
287 |
g_kqueue_file_monitor_finalize (GObject *object) |
288 |
@@ -80,16 +140,18 @@ g_kqueue_file_monitor_finalize (GObject *object) |
289 |
|
290 |
if (kqueue_monitor->sub) |
291 |
{ |
292 |
- _kh_cancel_sub (kqueue_monitor->sub); |
293 |
- _kh_sub_free (kqueue_monitor->sub); |
294 |
+ _kqsub_cancel (kqueue_monitor->sub); |
295 |
+ _kqsub_free (kqueue_monitor->sub); |
296 |
kqueue_monitor->sub = NULL; |
297 |
} |
298 |
|
299 |
+#ifndef O_EVTONLY |
300 |
if (kqueue_monitor->fallback) |
301 |
g_object_unref (kqueue_monitor->fallback); |
302 |
|
303 |
if (kqueue_monitor->fbfile) |
304 |
g_object_unref (kqueue_monitor->fbfile); |
305 |
+#endif |
306 |
|
307 |
if (G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) |
308 |
(*G_OBJECT_CLASS (g_kqueue_file_monitor_parent_class)->finalize) (object); |
309 |
@@ -103,21 +165,25 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor, |
310 |
GFileMonitorSource *source) |
311 |
{ |
312 |
GKqueueFileMonitor *kqueue_monitor = G_KQUEUE_FILE_MONITOR (local_monitor); |
313 |
- GObject *obj; |
314 |
- GKqueueFileMonitorClass *klass; |
315 |
- GObjectClass *parent_class; |
316 |
- kqueue_sub *sub = NULL; |
317 |
- gboolean ret_kh_startup = FALSE; |
318 |
- const gchar *path = NULL; |
319 |
- |
320 |
- |
321 |
- ret_kh_startup = _kh_startup (); |
322 |
- g_assert (ret_kh_startup); |
323 |
+ kqueue_sub *sub; |
324 |
+ const gchar *path; |
325 |
|
326 |
path = filename; |
327 |
- if (!path) |
328 |
+ if (path == NULL) |
329 |
path = dirname; |
330 |
|
331 |
+#ifndef O_EVTONLY |
332 |
+ if (_ke_is_excluded (path)) |
333 |
+ { |
334 |
+ GFile *file = g_file_new_for_path (path); |
335 |
+ kqueue_monitor->fbfile = file; |
336 |
+ kqueue_monitor->fallback = _g_poll_file_monitor_new (file); |
337 |
+ g_signal_connect (kqueue_monitor->fallback, "changed", |
338 |
+ G_CALLBACK (_fallback_callback), kqueue_monitor); |
339 |
+ return; |
340 |
+ } |
341 |
+#endif |
342 |
+ |
343 |
/* For a directory monitor, create a subscription object anyway. |
344 |
* It will be used for directory diff calculation routines. |
345 |
* Wait, directory diff in a GKqueueFileMonitor? |
346 |
@@ -125,33 +191,13 @@ g_kqueue_file_monitor_start (GLocalFileMonitor *local_monitor, |
347 |
* file, GIO uses a GKqueueFileMonitor object for that. If a directory |
348 |
* will be created under that path, GKqueueFileMonitor will have to |
349 |
* handle the directory notifications. */ |
350 |
+ sub = _kqsub_new (path, local_monitor, source); |
351 |
+ if (sub == NULL) |
352 |
+ return; |
353 |
|
354 |
- sub = _kh_sub_new (path, TRUE, source); |
355 |
- |
356 |
- /* FIXME: what to do about errors here? we can't return NULL or another |
357 |
- * kind of error and an assertion is probably too hard (same issue as in |
358 |
- * the inotify backend) */ |
359 |
- g_assert (sub != NULL); |
360 |
kqueue_monitor->sub = sub; |
361 |
- |
362 |
- if (!_ke_is_excluded (path)) |
363 |
- _kh_add_sub (sub); |
364 |
- else |
365 |
- { |
366 |
- GFile *file = g_file_new_for_path (path); |
367 |
- kqueue_monitor->fbfile = file; |
368 |
- kqueue_monitor->fallback = _g_poll_file_monitor_new (file); |
369 |
- g_signal_connect (kqueue_monitor->fallback, |
370 |
- "changed", |
371 |
- G_CALLBACK (_fallback_callback), |
372 |
- kqueue_monitor); |
373 |
- } |
374 |
-} |
375 |
- |
376 |
-static gboolean |
377 |
-g_kqueue_file_monitor_is_supported (void) |
378 |
-{ |
379 |
- return _kh_startup (); |
380 |
+ if (!_kqsub_start_watching (sub)) |
381 |
+ _km_add_missing (sub); |
382 |
} |
383 |
|
384 |
static void |
385 |
@@ -174,6 +220,101 @@ g_kqueue_file_monitor_init (GKqueueFileMonitor *monitor) |
386 |
{ |
387 |
} |
388 |
|
389 |
+static gboolean |
390 |
+g_kqueue_file_monitor_callback (gint fd, GIOCondition condition, gpointer user_data) |
391 |
+{ |
392 |
+ gint64 now = g_source_get_time (kq_source); |
393 |
+ kqueue_sub *sub; |
394 |
+ GFileMonitorSource *source; |
395 |
+ struct kevent ev; |
396 |
+ struct timespec ts; |
397 |
+ |
398 |
+ memset (&ts, 0, sizeof(ts)); |
399 |
+ while (kevent(fd, NULL, 0, &ev, 1, &ts) > 0) |
400 |
+ { |
401 |
+ GFileMonitorEvent mask = 0; |
402 |
+ |
403 |
+ if (ev.filter != EVFILT_VNODE || ev.udata == NULL) |
404 |
+ continue; |
405 |
+ |
406 |
+ sub = ev.udata; |
407 |
+ source = sub->source; |
408 |
+ |
409 |
+ if (ev.flags & EV_ERROR) |
410 |
+ ev.fflags = NOTE_REVOKE; |
411 |
+ |
412 |
+ if (ev.fflags & (NOTE_DELETE | NOTE_REVOKE)) |
413 |
+ { |
414 |
+ _kqsub_cancel (sub); |
415 |
+ _km_add_missing (sub); |
416 |
+ } |
417 |
+ |
418 |
+ if (sub->is_dir && ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) |
419 |
+ { |
420 |
+ _kh_dir_diff (sub); |
421 |
+ ev.fflags &= ~(NOTE_WRITE | NOTE_EXTEND); |
422 |
+ } |
423 |
+ |
424 |
+ if (ev.fflags & NOTE_DELETE) |
425 |
+ { |
426 |
+ mask = G_FILE_MONITOR_EVENT_DELETED; |
427 |
+ } |
428 |
+ else if (ev.fflags & NOTE_ATTRIB) |
429 |
+ { |
430 |
+ mask = G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; |
431 |
+ } |
432 |
+ else if (ev.fflags & (NOTE_WRITE | NOTE_EXTEND)) |
433 |
+ { |
434 |
+ mask = G_FILE_MONITOR_EVENT_CHANGED; |
435 |
+ } |
436 |
+ else if (ev.fflags & NOTE_RENAME) |
437 |
+ { |
438 |
+ /* Since there’s apparently no way to get the new name of the |
439 |
+ * file out of kqueue(), all we can do is say that this one has |
440 |
+ * been deleted. */ |
441 |
+ mask = G_FILE_MONITOR_EVENT_DELETED; |
442 |
+ } |
443 |
+ else if (ev.fflags & NOTE_REVOKE) |
444 |
+ { |
445 |
+ mask = G_FILE_MONITOR_EVENT_UNMOUNTED; |
446 |
+ } |
447 |
+ |
448 |
+ if (mask) |
449 |
+ g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, now); |
450 |
+ } |
451 |
+ |
452 |
+ return TRUE; |
453 |
+} |
454 |
+ |
455 |
+static gboolean |
456 |
+g_kqueue_file_monitor_is_supported (void) |
457 |
+{ |
458 |
+ int errsv; |
459 |
+ |
460 |
+ G_LOCK (kq_lock); |
461 |
+ |
462 |
+ if (kq_queue == -1) |
463 |
+ { |
464 |
+ kq_queue = kqueue (); |
465 |
+ errsv = errno; |
466 |
+ |
467 |
+ if (kq_queue == -1) |
468 |
+ { |
469 |
+ g_warning ("Unable to create a kqueue: %s", g_strerror (errsv)); |
470 |
+ G_UNLOCK (kq_lock); |
471 |
+ return FALSE; |
472 |
+ } |
473 |
+ |
474 |
+ kq_source = g_unix_fd_source_new (kq_queue, G_IO_IN); |
475 |
+ g_source_set_callback (kq_source, (GSourceFunc) g_kqueue_file_monitor_callback, NULL, NULL); |
476 |
+ g_source_attach (kq_source, GLIB_PRIVATE_CALL (g_get_worker_context) ()); |
477 |
+ } |
478 |
+ |
479 |
+ G_UNLOCK (kq_lock); |
480 |
+ |
481 |
+ return TRUE; |
482 |
+} |
483 |
+ |
484 |
static gboolean |
485 |
g_kqueue_file_monitor_cancel (GFileMonitor *monitor) |
486 |
{ |
487 |
@@ -181,18 +322,117 @@ g_kqueue_file_monitor_cancel (GFileMonitor *monitor) |
488 |
|
489 |
if (kqueue_monitor->sub) |
490 |
{ |
491 |
- _kh_cancel_sub (kqueue_monitor->sub); |
492 |
- _kh_sub_free (kqueue_monitor->sub); |
493 |
+ _kqsub_cancel (kqueue_monitor->sub); |
494 |
+ _kqsub_free (kqueue_monitor->sub); |
495 |
kqueue_monitor->sub = NULL; |
496 |
} |
497 |
+#ifndef O_EVTONLY |
498 |
else if (kqueue_monitor->fallback) |
499 |
{ |
500 |
g_signal_handlers_disconnect_by_func (kqueue_monitor->fallback, _fallback_callback, kqueue_monitor); |
501 |
g_file_monitor_cancel (kqueue_monitor->fallback); |
502 |
} |
503 |
+#endif |
504 |
|
505 |
if (G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) |
506 |
(*G_FILE_MONITOR_CLASS (g_kqueue_file_monitor_parent_class)->cancel) (monitor); |
507 |
|
508 |
return TRUE; |
509 |
} |
510 |
+ |
511 |
+static kqueue_sub * |
512 |
+_kqsub_new (const gchar *filename, GLocalFileMonitor *mon, GFileMonitorSource *source) |
513 |
+{ |
514 |
+ kqueue_sub *sub; |
515 |
+ |
516 |
+ sub = g_slice_new (kqueue_sub); |
517 |
+ sub->filename = g_strdup (filename); |
518 |
+ sub->mon = mon; |
519 |
+ g_source_ref ((GSource *) source); |
520 |
+ sub->source = source; |
521 |
+ sub->fd = -1; |
522 |
+ sub->deps = NULL; |
523 |
+ sub->is_dir = 0; |
524 |
+ |
525 |
+ return sub; |
526 |
+} |
527 |
+ |
528 |
+static void |
529 |
+_kqsub_free (kqueue_sub *sub) |
530 |
+{ |
531 |
+ g_assert (sub->deps == NULL); |
532 |
+ g_assert (sub->fd == -1); |
533 |
+ |
534 |
+ g_source_unref ((GSource *) sub->source); |
535 |
+ g_free (sub->filename); |
536 |
+ g_slice_free (kqueue_sub, sub); |
537 |
+} |
538 |
+ |
539 |
+static gboolean |
540 |
+_kqsub_cancel (kqueue_sub *sub) |
541 |
+{ |
542 |
+ struct kevent ev; |
543 |
+ |
544 |
+ if (sub->deps) |
545 |
+ { |
546 |
+ dl_free (sub->deps); |
547 |
+ sub->deps = NULL; |
548 |
+ } |
549 |
+ |
550 |
+ _km_remove (sub); |
551 |
+ |
552 |
+ /* Only in the missing list? We're done! */ |
553 |
+ if (sub->fd == -1) |
554 |
+ return TRUE; |
555 |
+ |
556 |
+ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_DELETE, NOTE_ALL, 0, sub); |
557 |
+ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) |
558 |
+ { |
559 |
+ g_warning ("Unable to remove event for %s: %s", sub->filename, g_strerror (errno)); |
560 |
+ return FALSE; |
561 |
+ } |
562 |
+ |
563 |
+ close (sub->fd); |
564 |
+ sub->fd = -1; |
565 |
+ |
566 |
+ return TRUE; |
567 |
+} |
568 |
+ |
569 |
+gboolean |
570 |
+_kqsub_start_watching (kqueue_sub *sub) |
571 |
+{ |
572 |
+ struct stat st; |
573 |
+ struct kevent ev; |
574 |
+ |
575 |
+ sub->fd = open (sub->filename, O_KQFLAG); |
576 |
+ if (sub->fd == -1) |
577 |
+ return FALSE; |
578 |
+ |
579 |
+ if (fstat (sub->fd, &st) == -1) |
580 |
+ { |
581 |
+ g_warning ("fstat failed for %s: %s", sub->filename, g_strerror (errno)); |
582 |
+ close (sub->fd); |
583 |
+ sub->fd = -1; |
584 |
+ return FALSE; |
585 |
+ } |
586 |
+ |
587 |
+ sub->is_dir = (st.st_mode & S_IFDIR) ? 1 : 0; |
588 |
+ if (sub->is_dir) |
589 |
+ { |
590 |
+ if (sub->deps) |
591 |
+ dl_free (sub->deps); |
592 |
+ |
593 |
+ sub->deps = dl_listing (sub->filename); |
594 |
+ } |
595 |
+ |
596 |
+ EV_SET (&ev, sub->fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_ALL, 0, sub); |
597 |
+ if (kevent (kq_queue, &ev, 1, NULL, 0, NULL) == -1) |
598 |
+ { |
599 |
+ g_warning ("Unable to add event for %s: %s", sub->filename, g_strerror (errno)); |
600 |
+ close (sub->fd); |
601 |
+ sub->fd = -1; |
602 |
+ return FALSE; |
603 |
+ } |
604 |
+ |
605 |
+ return TRUE; |
606 |
+} |
607 |
diff --git gio/kqueue/gkqueuefilemonitor.h gio/kqueue/gkqueuefilemonitor.h |
608 |
deleted file mode 100644 |
609 |
index 32752f105..000000000 |
610 |
--- gio/kqueue/gkqueuefilemonitor.h |
611 |
+++ /dev/null |
612 |
@@ -1,51 +0,0 @@ |
613 |
-/******************************************************************************* |
614 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
615 |
- |
616 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
617 |
- of this software and associated documentation files (the "Software"), to deal |
618 |
- in the Software without restriction, including without limitation the rights |
619 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
620 |
- copies of the Software, and to permit persons to whom the Software is |
621 |
- furnished to do so, subject to the following conditions: |
622 |
- |
623 |
- The above copyright notice and this permission notice shall be included in |
624 |
- all copies or substantial portions of the Software. |
625 |
- |
626 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
627 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
628 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
629 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
630 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
631 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
632 |
- THE SOFTWARE. |
633 |
-*******************************************************************************/ |
634 |
- |
635 |
-#ifndef __G_KQUEUE_FILE_MONITOR_H__ |
636 |
-#define __G_KQUEUE_FILE_MONITOR_H__ |
637 |
- |
638 |
-#include <glib-object.h> |
639 |
-#include <string.h> |
640 |
-#include <gio/gfilemonitor.h> |
641 |
-#include <gio/glocalfilemonitor.h> |
642 |
-#include <gio/giomodule.h> |
643 |
- |
644 |
-G_BEGIN_DECLS |
645 |
- |
646 |
-#define G_TYPE_KQUEUE_FILE_MONITOR (g_kqueue_file_monitor_get_type ()) |
647 |
-#define G_KQUEUE_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitor)) |
648 |
-#define G_KQUEUE_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), G_TYPE_KQUEUE_FILE_MONITOR, GKqueueFileMonitorClass)) |
649 |
-#define G_IS_KQUEUE_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_KQUEUE_FILE_MONITOR)) |
650 |
-#define G_IS_KQUEUE_FILE_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_KQUEUE_FILE_MONITOR)) |
651 |
- |
652 |
-typedef struct _GKqueueFileMonitor GKqueueFileMonitor; |
653 |
-typedef struct _GKqueueFileMonitorClass GKqueueFileMonitorClass; |
654 |
- |
655 |
-struct _GKqueueFileMonitorClass { |
656 |
- GLocalFileMonitorClass parent_class; |
657 |
-}; |
658 |
- |
659 |
-GType g_kqueue_file_monitor_get_type (void); |
660 |
- |
661 |
-G_END_DECLS |
662 |
- |
663 |
-#endif /* __G_KQUEUE_FILE_MONITOR_H__ */ |
664 |
diff --git gio/kqueue/kqueue-exclusions.c gio/kqueue/kqueue-exclusions.c |
665 |
deleted file mode 100644 |
666 |
index 748d7a92a..000000000 |
667 |
--- gio/kqueue/kqueue-exclusions.c |
668 |
+++ /dev/null |
669 |
@@ -1,65 +0,0 @@ |
670 |
-/******************************************************************************* |
671 |
- Copyright (c) 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
672 |
- Copyright (c) 2012 Antoine Jacoutot <ajacoutot@openbsd.org> |
673 |
- |
674 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
675 |
- of this software and associated documentation files (the "Software"), to deal |
676 |
- in the Software without restriction, including without limitation the rights |
677 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
678 |
- copies of the Software, and to permit persons to whom the Software is |
679 |
- furnished to do so, subject to the following conditions: |
680 |
- |
681 |
- The above copyright notice and this permission notice shall be included in |
682 |
- all copies or substantial portions of the Software. |
683 |
- |
684 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
685 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
686 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
687 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
688 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
689 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
690 |
- THE SOFTWARE. |
691 |
-*******************************************************************************/ |
692 |
- |
693 |
-#include <fcntl.h> |
694 |
-#include <glib.h> |
695 |
-#include <gio/gio.h> |
696 |
-#include "kqueue-exclusions.h" |
697 |
- |
698 |
-static gboolean ke_debug_enabled = FALSE; |
699 |
-#define KE_W if (ke_debug_enabled) g_warning |
700 |
- |
701 |
-/* |
702 |
- * _ke_is_excluded: |
703 |
- * @full_path - a path to file to check. |
704 |
- * |
705 |
- * Returns: TRUE if the file should be excluded from the kqueue-powered |
706 |
- * monitoring, FALSE otherwise. |
707 |
- **/ |
708 |
-gboolean |
709 |
-_ke_is_excluded (const char *full_path) |
710 |
-{ |
711 |
-#if defined (O_EVTONLY) |
712 |
- return FALSE; |
713 |
-#else |
714 |
- GFile *f = NULL; |
715 |
- GMount *mount = NULL; |
716 |
- |
717 |
- f = g_file_new_for_path (full_path); |
718 |
- |
719 |
- if (f != NULL) { |
720 |
- mount = g_file_find_enclosing_mount (f, NULL, NULL); |
721 |
- g_object_unref (f); |
722 |
- } |
723 |
- |
724 |
- if ((mount != NULL && (g_mount_can_unmount (mount))) || g_str_has_prefix (full_path, "/mnt/")) |
725 |
- { |
726 |
- KE_W ("Excluding %s from kernel notification, falling back to poll", full_path); |
727 |
- if (mount) |
728 |
- g_object_unref (mount); |
729 |
- return TRUE; |
730 |
- } |
731 |
- else |
732 |
- return FALSE; |
733 |
-#endif |
734 |
-} |
735 |
diff --git gio/kqueue/kqueue-exclusions.h gio/kqueue/kqueue-exclusions.h |
736 |
deleted file mode 100644 |
737 |
index f1dad0e7e..000000000 |
738 |
--- gio/kqueue/kqueue-exclusions.h |
739 |
+++ /dev/null |
740 |
@@ -1,28 +0,0 @@ |
741 |
-/******************************************************************************* |
742 |
- Copyright (c) 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
743 |
- |
744 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
745 |
- of this software and associated documentation files (the "Software"), to deal |
746 |
- in the Software without restriction, including without limitation the rights |
747 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
748 |
- copies of the Software, and to permit persons to whom the Software is |
749 |
- furnished to do so, subject to the following conditions: |
750 |
- |
751 |
- The above copyright notice and this permission notice shall be included in |
752 |
- all copies or substantial portions of the Software. |
753 |
- |
754 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
755 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
756 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
757 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
758 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
759 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
760 |
- THE SOFTWARE. |
761 |
-*******************************************************************************/ |
762 |
- |
763 |
-#ifndef __KQUEUE_EXCLUSIONS_H |
764 |
-#define __KQUEUE_EXCLUSIONS_H |
765 |
- |
766 |
-gboolean _ke_is_excluded (const char *full_path); |
767 |
- |
768 |
-#endif /* __KQUEUE_EXCLUDES_H */ |
769 |
diff --git gio/kqueue/kqueue-helper.c gio/kqueue/kqueue-helper.c |
770 |
index e7d583c8b..497c30b15 100644 |
771 |
--- gio/kqueue/kqueue-helper.c |
772 |
+++ gio/kqueue/kqueue-helper.c |
773 |
@@ -34,83 +34,6 @@ |
774 |
#include <errno.h> |
775 |
#include <pthread.h> |
776 |
#include "kqueue-helper.h" |
777 |
-#include "kqueue-utils.h" |
778 |
-#include "kqueue-thread.h" |
779 |
-#include "kqueue-missing.h" |
780 |
-#include "kqueue-exclusions.h" |
781 |
- |
782 |
-static gboolean kh_debug_enabled = FALSE; |
783 |
-#define KH_W if (kh_debug_enabled) g_warning |
784 |
- |
785 |
-static GHashTable *subs_hash_table = NULL; |
786 |
-G_LOCK_DEFINE_STATIC (hash_lock); |
787 |
- |
788 |
-static int kqueue_descriptor = -1; |
789 |
-static int kqueue_socket_pair[] = {-1, -1}; |
790 |
-static pthread_t kqueue_thread; |
791 |
- |
792 |
- |
793 |
-void _kh_file_appeared_cb (kqueue_sub *sub); |
794 |
- |
795 |
-/** |
796 |
- * accessor function for kqueue_descriptor |
797 |
- **/ |
798 |
-int |
799 |
-get_kqueue_descriptor() |
800 |
-{ |
801 |
- return kqueue_descriptor; |
802 |
-} |
803 |
- |
804 |
-/** |
805 |
- * convert_kqueue_events_to_gio: |
806 |
- * @flags: a set of kqueue filter flags |
807 |
- * @done: a pointer to #gboolean indicating that the |
808 |
- * conversion has been done (out) |
809 |
- * |
810 |
- * Translates kqueue filter flags into GIO event flags. |
811 |
- * |
812 |
- * Returns: a #GFileMonitorEvent |
813 |
- **/ |
814 |
-static GFileMonitorEvent |
815 |
-convert_kqueue_events_to_gio (uint32_t flags, gboolean *done) |
816 |
-{ |
817 |
- g_assert (done != NULL); |
818 |
- *done = FALSE; |
819 |
- |
820 |
- /* TODO: The following notifications should be emulated, if possible: |
821 |
- * - G_FILE_MONITOR_EVENT_PRE_UNMOUNT |
822 |
- */ |
823 |
- if (flags & NOTE_DELETE) |
824 |
- { |
825 |
- *done = TRUE; |
826 |
- return G_FILE_MONITOR_EVENT_DELETED; |
827 |
- } |
828 |
- if (flags & NOTE_ATTRIB) |
829 |
- { |
830 |
- *done = TRUE; |
831 |
- return G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED; |
832 |
- } |
833 |
- if (flags & (NOTE_WRITE | NOTE_EXTEND)) |
834 |
- { |
835 |
- *done = TRUE; |
836 |
- return G_FILE_MONITOR_EVENT_CHANGED; |
837 |
- } |
838 |
- if (flags & NOTE_RENAME) |
839 |
- { |
840 |
- /* Since there’s apparently no way to get the new name of the file out of |
841 |
- * kqueue(), all we can do is say that this one has been deleted. */ |
842 |
- *done = TRUE; |
843 |
- return G_FILE_MONITOR_EVENT_DELETED; |
844 |
- } |
845 |
- if (flags & NOTE_REVOKE) |
846 |
- { |
847 |
- *done = TRUE; |
848 |
- return G_FILE_MONITOR_EVENT_UNMOUNTED; |
849 |
- } |
850 |
- |
851 |
- /* done is FALSE */ |
852 |
- return 0; |
853 |
-} |
854 |
|
855 |
typedef struct { |
856 |
kqueue_sub *sub; |
857 |
@@ -238,318 +161,21 @@ static const traverse_cbs cbs = { |
858 |
|
859 |
|
860 |
void |
861 |
-_kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source) |
862 |
+_kh_dir_diff (kqueue_sub *sub) |
863 |
{ |
864 |
dep_list *was; |
865 |
handle_ctx ctx; |
866 |
|
867 |
- g_assert (sub != NULL); |
868 |
- g_assert (source != NULL); |
869 |
- |
870 |
memset (&ctx, 0, sizeof (handle_ctx)); |
871 |
ctx.sub = sub; |
872 |
- ctx.source = source; |
873 |
+ ctx.source = sub->source; |
874 |
|
875 |
was = sub->deps; |
876 |
sub->deps = dl_listing (sub->filename); |
877 |
- |
878 |
+ |
879 |
dl_calculate (was, sub->deps, &cbs, &ctx); |
880 |
|
881 |
dl_free (was); |
882 |
} |
883 |
|
884 |
|
885 |
-/** |
886 |
- * process_kqueue_notifications: |
887 |
- * @gioc: unused. |
888 |
- * @cond: unused. |
889 |
- * @data: unused. |
890 |
- * |
891 |
- * Processes notifications, coming from the kqueue thread. |
892 |
- * |
893 |
- * Reads notifications from the command file descriptor, emits the |
894 |
- * "changed" event on the appropriate monitor. |
895 |
- * |
896 |
- * A typical GIO Channel callback function. |
897 |
- * |
898 |
- * Returns: %TRUE |
899 |
- **/ |
900 |
-static gboolean |
901 |
-process_kqueue_notifications (GIOChannel *gioc, |
902 |
- GIOCondition cond, |
903 |
- gpointer data) |
904 |
-{ |
905 |
- struct kqueue_notification n; |
906 |
- kqueue_sub *sub = NULL; |
907 |
- GFileMonitorSource *source = NULL; |
908 |
- GFileMonitorEvent mask = 0; |
909 |
- |
910 |
- g_assert (kqueue_socket_pair[0] != -1); |
911 |
- if (!_ku_read (kqueue_socket_pair[0], &n, sizeof (struct kqueue_notification))) |
912 |
- { |
913 |
- KH_W ("Failed to read a kqueue notification, error %d", errno); |
914 |
- return TRUE; |
915 |
- } |
916 |
- |
917 |
- G_LOCK (hash_lock); |
918 |
- sub = (kqueue_sub *) g_hash_table_lookup (subs_hash_table, GINT_TO_POINTER (n.fd)); |
919 |
- G_UNLOCK (hash_lock); |
920 |
- |
921 |
- if (sub == NULL) |
922 |
- { |
923 |
- KH_W ("Got a notification for a deleted or non-existing subscription %d", |
924 |
- n.fd); |
925 |
- return TRUE; |
926 |
- } |
927 |
- |
928 |
- source = sub->user_data; |
929 |
- g_assert (source != NULL); |
930 |
- |
931 |
- if (n.flags & (NOTE_DELETE | NOTE_REVOKE)) |
932 |
- { |
933 |
- if (sub->deps) |
934 |
- { |
935 |
- dl_free (sub->deps); |
936 |
- sub->deps = NULL; |
937 |
- } |
938 |
- _km_add_missing (sub); |
939 |
- |
940 |
- if (!(n.flags & NOTE_REVOKE)) |
941 |
- { |
942 |
- /* Note that NOTE_REVOKE is issued by the kqueue thread |
943 |
- * on EV_ERROR kevent. In this case, a file descriptor is |
944 |
- * already closed from the kqueue thread, no need to close |
945 |
- * it manually */ |
946 |
- _kh_cancel_sub (sub); |
947 |
- } |
948 |
- } |
949 |
- |
950 |
- if (sub->is_dir && n.flags & (NOTE_WRITE | NOTE_EXTEND)) |
951 |
- { |
952 |
- _kh_dir_diff (sub, source); |
953 |
- n.flags &= ~(NOTE_WRITE | NOTE_EXTEND); |
954 |
- } |
955 |
- |
956 |
- if (n.flags) |
957 |
- { |
958 |
- gboolean done = FALSE; |
959 |
- mask = convert_kqueue_events_to_gio (n.flags, &done); |
960 |
- if (done == TRUE) |
961 |
- g_file_monitor_source_handle_event (source, mask, NULL, NULL, NULL, g_get_monotonic_time ()); |
962 |
- } |
963 |
- |
964 |
- return TRUE; |
965 |
-} |
966 |
- |
967 |
- |
968 |
-/* |
969 |
- * _kh_startup_impl: |
970 |
- * @unused: unused |
971 |
- * |
972 |
- * Kqueue backend startup code. Should be called only once. |
973 |
- * |
974 |
- * Returns: %TRUE on success, %FALSE otherwise. |
975 |
- **/ |
976 |
-static gpointer |
977 |
-_kh_startup_impl (gpointer unused) |
978 |
-{ |
979 |
- GIOChannel *channel = NULL; |
980 |
- gboolean result = FALSE; |
981 |
- |
982 |
- kqueue_descriptor = kqueue (); |
983 |
- result = (kqueue_descriptor != -1); |
984 |
- if (!result) |
985 |
- { |
986 |
- KH_W ("Failed to initialize kqueue\n!"); |
987 |
- return GINT_TO_POINTER (FALSE); |
988 |
- } |
989 |
- |
990 |
- result = socketpair (AF_UNIX, SOCK_STREAM, 0, kqueue_socket_pair); |
991 |
- if (result != 0) |
992 |
- { |
993 |
- KH_W ("Failed to create socket pair\n!"); |
994 |
- return GINT_TO_POINTER (FALSE) ; |
995 |
- } |
996 |
- |
997 |
- result = pthread_create (&kqueue_thread, |
998 |
- NULL, |
999 |
- _kqueue_thread_func, |
1000 |
- &kqueue_socket_pair[1]); |
1001 |
- if (result != 0) |
1002 |
- { |
1003 |
- KH_W ("Failed to run kqueue thread\n!"); |
1004 |
- return GINT_TO_POINTER (FALSE); |
1005 |
- } |
1006 |
- |
1007 |
- _km_init (_kh_file_appeared_cb); |
1008 |
- |
1009 |
- channel = g_io_channel_unix_new (kqueue_socket_pair[0]); |
1010 |
- g_io_add_watch (channel, G_IO_IN, process_kqueue_notifications, NULL); |
1011 |
- |
1012 |
- subs_hash_table = g_hash_table_new (g_direct_hash, g_direct_equal); |
1013 |
- |
1014 |
- KH_W ("started gio kqueue backend\n"); |
1015 |
- return GINT_TO_POINTER (TRUE); |
1016 |
-} |
1017 |
- |
1018 |
- |
1019 |
-/* |
1020 |
- * _kh_startup: |
1021 |
- * Kqueue backend initialization. |
1022 |
- * |
1023 |
- * Returns: %TRUE on success, %FALSE otherwise. |
1024 |
- **/ |
1025 |
-gboolean |
1026 |
-_kh_startup (void) |
1027 |
-{ |
1028 |
- static GOnce init_once = G_ONCE_INIT; |
1029 |
- g_once (&init_once, _kh_startup_impl, NULL); |
1030 |
- return GPOINTER_TO_INT (init_once.retval); |
1031 |
-} |
1032 |
- |
1033 |
- |
1034 |
-/** |
1035 |
- * _kh_start_watching: |
1036 |
- * @sub: a #kqueue_sub |
1037 |
- * |
1038 |
- * Starts watching on a subscription. |
1039 |
- * |
1040 |
- * Returns: %TRUE on success, %FALSE otherwise. |
1041 |
- **/ |
1042 |
-gboolean |
1043 |
-_kh_start_watching (kqueue_sub *sub) |
1044 |
-{ |
1045 |
- g_assert (kqueue_socket_pair[0] != -1); |
1046 |
- g_assert (sub != NULL); |
1047 |
- g_assert (sub->filename != NULL); |
1048 |
- |
1049 |
- /* kqueue requires a file descriptor to monitor. Sad but true */ |
1050 |
-#if defined (O_EVTONLY) |
1051 |
- sub->fd = open (sub->filename, O_EVTONLY); |
1052 |
-#else |
1053 |
- sub->fd = open (sub->filename, O_RDONLY); |
1054 |
-#endif |
1055 |
- |
1056 |
- if (sub->fd == -1) |
1057 |
- { |
1058 |
- KH_W ("failed to open file %s (error %d)", sub->filename, errno); |
1059 |
- return FALSE; |
1060 |
- } |
1061 |
- |
1062 |
- _ku_file_information (sub->fd, &sub->is_dir, NULL); |
1063 |
- if (sub->is_dir) |
1064 |
- { |
1065 |
- /* I know, it is very bad to make such decisions in this way and here. |
1066 |
- * We already do have an user_data at the #kqueue_sub, and it may point to |
1067 |
- * GKqueueFileMonitor or GKqueueDirectoryMonitor. For a directory case, |
1068 |
- * we need to scan in contents for the further diffs. Ideally this process |
1069 |
- * should be delegated to the GKqueueDirectoryMonitor, but for now I will |
1070 |
- * do it in a dirty way right here. */ |
1071 |
- if (sub->deps) |
1072 |
- dl_free (sub->deps); |
1073 |
- |
1074 |
- sub->deps = dl_listing (sub->filename); |
1075 |
- } |
1076 |
- |
1077 |
- G_LOCK (hash_lock); |
1078 |
- g_hash_table_insert (subs_hash_table, GINT_TO_POINTER (sub->fd), sub); |
1079 |
- G_UNLOCK (hash_lock); |
1080 |
- |
1081 |
- _kqueue_thread_push_fd (sub->fd); |
1082 |
- |
1083 |
- /* Bump the kqueue thread. It will pick up a new sub entry to monitor */ |
1084 |
- if (!_ku_write (kqueue_socket_pair[0], "A", 1)) |
1085 |
- KH_W ("Failed to bump the kqueue thread (add fd, error %d)", errno); |
1086 |
- return TRUE; |
1087 |
-} |
1088 |
- |
1089 |
- |
1090 |
-/** |
1091 |
- * _kh_add_sub: |
1092 |
- * @sub: a #kqueue_sub |
1093 |
- * |
1094 |
- * Adds a subscription for monitoring. |
1095 |
- * |
1096 |
- * This funciton tries to start watching a subscription with |
1097 |
- * _kh_start_watching(). On failure, i.e. when a file does not exist yet, |
1098 |
- * the subscription will be added to a list of missing files to continue |
1099 |
- * watching when the file will appear. |
1100 |
- * |
1101 |
- * Returns: %TRUE |
1102 |
- **/ |
1103 |
-gboolean |
1104 |
-_kh_add_sub (kqueue_sub *sub) |
1105 |
-{ |
1106 |
- g_assert (sub != NULL); |
1107 |
- |
1108 |
- if (!_kh_start_watching (sub)) |
1109 |
- _km_add_missing (sub); |
1110 |
- |
1111 |
- return TRUE; |
1112 |
-} |
1113 |
- |
1114 |
- |
1115 |
-/** |
1116 |
- * _kh_cancel_sub: |
1117 |
- * @sub a #kqueue_sub |
1118 |
- * |
1119 |
- * Stops monitoring on a subscription. |
1120 |
- * |
1121 |
- * Returns: %TRUE |
1122 |
- **/ |
1123 |
-gboolean |
1124 |
-_kh_cancel_sub (kqueue_sub *sub) |
1125 |
-{ |
1126 |
- gboolean removed = FALSE; |
1127 |
- g_assert (kqueue_socket_pair[0] != -1); |
1128 |
- g_assert (sub != NULL); |
1129 |
- |
1130 |
- _km_remove (sub); |
1131 |
- |
1132 |
- G_LOCK (hash_lock); |
1133 |
- removed = g_hash_table_remove (subs_hash_table, GINT_TO_POINTER (sub->fd)); |
1134 |
- G_UNLOCK (hash_lock); |
1135 |
- |
1136 |
- if (removed) |
1137 |
- { |
1138 |
- /* fd will be closed in the kqueue thread */ |
1139 |
- _kqueue_thread_remove_fd (sub->fd); |
1140 |
- |
1141 |
- /* Bump the kqueue thread. It will pick up a new sub entry to remove*/ |
1142 |
- if (!_ku_write (kqueue_socket_pair[0], "R", 1)) |
1143 |
- KH_W ("Failed to bump the kqueue thread (remove fd, error %d)", errno); |
1144 |
- } |
1145 |
- |
1146 |
- return TRUE; |
1147 |
-} |
1148 |
- |
1149 |
- |
1150 |
-/** |
1151 |
- * _kh_file_appeared_cb: |
1152 |
- * @sub: a #kqueue_sub |
1153 |
- * |
1154 |
- * A callback function for kqueue-missing subsystem. |
1155 |
- * |
1156 |
- * Signals that a missing file has finally appeared in the filesystem. |
1157 |
- * Emits %G_FILE_MONITOR_EVENT_CREATED. |
1158 |
- **/ |
1159 |
-void |
1160 |
-_kh_file_appeared_cb (kqueue_sub *sub) |
1161 |
-{ |
1162 |
- GFile* child; |
1163 |
- |
1164 |
- g_assert (sub != NULL); |
1165 |
- g_assert (sub->filename); |
1166 |
- |
1167 |
- if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS)) |
1168 |
- return; |
1169 |
- |
1170 |
- child = g_file_new_for_path (sub->filename); |
1171 |
- |
1172 |
- g_file_monitor_emit_event (G_FILE_MONITOR (sub->user_data), |
1173 |
- child, |
1174 |
- NULL, |
1175 |
- G_FILE_MONITOR_EVENT_CREATED); |
1176 |
- |
1177 |
- g_object_unref (child); |
1178 |
-} |
1179 |
diff --git gio/kqueue/kqueue-helper.h gio/kqueue/kqueue-helper.h |
1180 |
index b12a28fae..38a32a2f9 100644 |
1181 |
--- gio/kqueue/kqueue-helper.h |
1182 |
+++ gio/kqueue/kqueue-helper.h |
1183 |
@@ -23,16 +23,31 @@ |
1184 |
#ifndef __KQUEUE_HELPER_H |
1185 |
#define __KQUEUE_HELPER_H |
1186 |
|
1187 |
-#include "kqueue-sub.h" |
1188 |
#include <gio/glocalfilemonitor.h> |
1189 |
#include <gio/gfilemonitor.h> |
1190 |
|
1191 |
-gboolean _kh_startup (void); |
1192 |
-gboolean _kh_add_sub (kqueue_sub *sub); |
1193 |
-gboolean _kh_cancel_sub (kqueue_sub *sub); |
1194 |
- |
1195 |
-gboolean _kh_start_watching (kqueue_sub *sub); |
1196 |
- |
1197 |
-void _kh_dir_diff (kqueue_sub *sub, GFileMonitorSource *source); |
1198 |
+#include "dep-list.h" |
1199 |
+ |
1200 |
+/** |
1201 |
+ * kqueue_sub: |
1202 |
+ * @filename: a name of the file to monitor |
1203 |
+ * @fd: the associated file descriptor (used by kqueue) |
1204 |
+ * |
1205 |
+ * Represents a subscription on a file or directory. |
1206 |
+ */ |
1207 |
+typedef struct |
1208 |
+{ |
1209 |
+ GLocalFileMonitor *mon; |
1210 |
+ GFileMonitorSource *source; |
1211 |
+ gchar* filename; |
1212 |
+ int fd; |
1213 |
+ dep_list* deps; |
1214 |
+ int is_dir; |
1215 |
+} kqueue_sub; |
1216 |
+ |
1217 |
+gboolean _kqsub_start_watching (kqueue_sub *sub); |
1218 |
+void _kh_dir_diff (kqueue_sub *sub); |
1219 |
+void _km_add_missing (kqueue_sub *sub); |
1220 |
+void _km_remove (kqueue_sub *sub); |
1221 |
|
1222 |
#endif /* __KQUEUE_HELPER_H */ |
1223 |
diff --git gio/kqueue/kqueue-missing.c gio/kqueue/kqueue-missing.c |
1224 |
index 9decdc937..93135b962 100644 |
1225 |
--- gio/kqueue/kqueue-missing.c |
1226 |
+++ gio/kqueue/kqueue-missing.c |
1227 |
@@ -23,12 +23,12 @@ |
1228 |
#include <glib.h> |
1229 |
|
1230 |
#include "kqueue-helper.h" |
1231 |
-#include "kqueue-sub.h" |
1232 |
-#include "kqueue-missing.h" |
1233 |
|
1234 |
|
1235 |
#define SCAN_MISSING_TIME 4 /* 1/4 Hz */ |
1236 |
|
1237 |
+void _kh_file_appeared_cb (kqueue_sub *sub); |
1238 |
+ |
1239 |
static gboolean km_scan_missing (gpointer user_data); |
1240 |
|
1241 |
static gboolean km_debug_enabled = FALSE; |
1242 |
@@ -38,21 +38,6 @@ static GSList *missing_subs_list = NULL; |
1243 |
G_LOCK_DEFINE_STATIC (missing_lock); |
1244 |
|
1245 |
static volatile gboolean scan_missing_running = FALSE; |
1246 |
-static on_create_cb file_appeared_callback; |
1247 |
- |
1248 |
- |
1249 |
-/** |
1250 |
- * _km_init: |
1251 |
- * @cb: a callback function. It will be called when a watched file |
1252 |
- * will appear. |
1253 |
- * |
1254 |
- * Initialize the kqueue-missing module (optional). |
1255 |
- **/ |
1256 |
-void |
1257 |
-_km_init (on_create_cb cb) |
1258 |
-{ |
1259 |
- file_appeared_callback = cb; |
1260 |
-} |
1261 |
|
1262 |
|
1263 |
/** |
1264 |
@@ -83,6 +68,35 @@ _km_add_missing (kqueue_sub *sub) |
1265 |
} |
1266 |
} |
1267 |
|
1268 |
+/** |
1269 |
+ * _kh_file_appeared_cb: |
1270 |
+ * @sub: a #kqueue_sub |
1271 |
+ * |
1272 |
+ * A callback function for kqueue-missing subsystem. |
1273 |
+ * |
1274 |
+ * Signals that a missing file has finally appeared in the filesystem. |
1275 |
+ * Emits %G_FILE_MONITOR_EVENT_CREATED. |
1276 |
+ **/ |
1277 |
+void |
1278 |
+_kh_file_appeared_cb (kqueue_sub *sub) |
1279 |
+{ |
1280 |
+ GFile *child; |
1281 |
+ |
1282 |
+ g_assert (sub != NULL); |
1283 |
+ g_assert (sub->filename); |
1284 |
+ |
1285 |
+ if (!g_file_test (sub->filename, G_FILE_TEST_EXISTS)) |
1286 |
+ return; |
1287 |
+ |
1288 |
+ child = g_file_new_for_path (sub->filename); |
1289 |
+ |
1290 |
+ g_file_monitor_emit_event (G_FILE_MONITOR (sub->mon), |
1291 |
+ child, |
1292 |
+ NULL, |
1293 |
+ G_FILE_MONITOR_EVENT_CREATED); |
1294 |
+ |
1295 |
+ g_object_unref (child); |
1296 |
+} |
1297 |
|
1298 |
/** |
1299 |
* km_scan_missing: |
1300 |
@@ -114,11 +128,10 @@ km_scan_missing (gpointer user_data) |
1301 |
g_assert (sub != NULL); |
1302 |
g_assert (sub->filename != NULL); |
1303 |
|
1304 |
- if (_kh_start_watching (sub)) |
1305 |
+ if (_kqsub_start_watching (sub)) |
1306 |
{ |
1307 |
KM_W ("file %s now exists, starting watching", sub->filename); |
1308 |
- if (file_appeared_callback) |
1309 |
- file_appeared_callback (sub); |
1310 |
+ _kh_file_appeared_cb (sub); |
1311 |
not_missing = g_slist_prepend (not_missing, head); |
1312 |
} |
1313 |
} |
1314 |
diff --git gio/kqueue/kqueue-missing.h gio/kqueue/kqueue-missing.h |
1315 |
deleted file mode 100644 |
1316 |
index 704a6f300..000000000 |
1317 |
--- gio/kqueue/kqueue-missing.h |
1318 |
+++ /dev/null |
1319 |
@@ -1,32 +0,0 @@ |
1320 |
-/******************************************************************************* |
1321 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1322 |
- |
1323 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1324 |
- of this software and associated documentation files (the "Software"), to deal |
1325 |
- in the Software without restriction, including without limitation the rights |
1326 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1327 |
- copies of the Software, and to permit persons to whom the Software is |
1328 |
- furnished to do so, subject to the following conditions: |
1329 |
- |
1330 |
- The above copyright notice and this permission notice shall be included in |
1331 |
- all copies or substantial portions of the Software. |
1332 |
- |
1333 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1334 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1335 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1336 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1337 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1338 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1339 |
- THE SOFTWARE. |
1340 |
-*******************************************************************************/ |
1341 |
- |
1342 |
-#ifndef __G_KQUEUE_MISSING_H |
1343 |
-#define __G_KQUEUE_MISSING_H |
1344 |
- |
1345 |
-typedef void (*on_create_cb) (kqueue_sub *); |
1346 |
- |
1347 |
-void _km_init (on_create_cb cb); |
1348 |
-void _km_add_missing (kqueue_sub *sub); |
1349 |
-void _km_remove (kqueue_sub *sub); |
1350 |
- |
1351 |
-#endif /* __G_KQUEUE_MISSING_H */ |
1352 |
diff --git gio/kqueue/kqueue-sub.c gio/kqueue/kqueue-sub.c |
1353 |
deleted file mode 100644 |
1354 |
index 8b864ba90..000000000 |
1355 |
--- gio/kqueue/kqueue-sub.c |
1356 |
+++ /dev/null |
1357 |
@@ -1,79 +0,0 @@ |
1358 |
-/******************************************************************************* |
1359 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1360 |
- |
1361 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1362 |
- of this software and associated documentation files (the "Software"), to deal |
1363 |
- in the Software without restriction, including without limitation the rights |
1364 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1365 |
- copies of the Software, and to permit persons to whom the Software is |
1366 |
- furnished to do so, subject to the following conditions: |
1367 |
- |
1368 |
- The above copyright notice and this permission notice shall be included in |
1369 |
- all copies or substantial portions of the Software. |
1370 |
- |
1371 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1372 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1373 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1374 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1375 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1376 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1377 |
- THE SOFTWARE. |
1378 |
-*******************************************************************************/ |
1379 |
- |
1380 |
-#include <glib.h> |
1381 |
- |
1382 |
-#include "kqueue-sub.h" |
1383 |
- |
1384 |
-static gboolean ks_debug_enabled = FALSE; |
1385 |
-#define KS_W if (ks_debug_enabled) g_warning |
1386 |
- |
1387 |
-/** |
1388 |
- * _kh_sub_new: |
1389 |
- * @filename: a file path to monitor (will be copied) |
1390 |
- * @pair_moves: pair moves flag. Refer to #GFileMonitorFlags documentation. |
1391 |
- * @user_data: user-supplied poiner. |
1392 |
- * |
1393 |
- * Creates a new subscription object. |
1394 |
- * |
1395 |
- * Returns: a pointer to a created subscription object. |
1396 |
- **/ |
1397 |
-kqueue_sub* |
1398 |
-_kh_sub_new (const gchar *filename, |
1399 |
- gboolean pair_moves, |
1400 |
- gpointer user_data) |
1401 |
-{ |
1402 |
- kqueue_sub *sub = g_slice_new (kqueue_sub); |
1403 |
- g_assert (sub != NULL); |
1404 |
- |
1405 |
- sub->filename = g_strdup (filename); |
1406 |
- sub->pair_moves = pair_moves; |
1407 |
- sub->user_data = user_data; |
1408 |
- sub->fd = -1; |
1409 |
- sub->deps = NULL; |
1410 |
- /* I think that having such flag in the subscription is not good */ |
1411 |
- sub->is_dir = 0; |
1412 |
- |
1413 |
- KS_W ("new subscription for %s being setup\n", sub->filename); |
1414 |
- |
1415 |
- return sub; |
1416 |
-} |
1417 |
- |
1418 |
- |
1419 |
-/** |
1420 |
- * _kh_sub_free: |
1421 |
- * @sub: a #kqueue_sub |
1422 |
- * |
1423 |
- * Frees a subscription object and all its associated memory. |
1424 |
- **/ |
1425 |
-void |
1426 |
-_kh_sub_free (kqueue_sub *sub) |
1427 |
-{ |
1428 |
- if (sub->deps) |
1429 |
- { |
1430 |
- dl_free (sub->deps); |
1431 |
- sub->deps = NULL; |
1432 |
- } |
1433 |
- |
1434 |
- g_free (sub->filename); |
1435 |
- g_slice_free (kqueue_sub, sub); |
1436 |
-} |
1437 |
diff --git gio/kqueue/kqueue-sub.h gio/kqueue/kqueue-sub.h |
1438 |
deleted file mode 100644 |
1439 |
index 215c49142..000000000 |
1440 |
--- gio/kqueue/kqueue-sub.h |
1441 |
+++ /dev/null |
1442 |
@@ -1,50 +0,0 @@ |
1443 |
-/******************************************************************************* |
1444 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1445 |
- |
1446 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1447 |
- of this software and associated documentation files (the "Software"), to deal |
1448 |
- in the Software without restriction, including without limitation the rights |
1449 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1450 |
- copies of the Software, and to permit persons to whom the Software is |
1451 |
- furnished to do so, subject to the following conditions: |
1452 |
- |
1453 |
- The above copyright notice and this permission notice shall be included in |
1454 |
- all copies or substantial portions of the Software. |
1455 |
- |
1456 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1457 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1458 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1459 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1460 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1461 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1462 |
- THE SOFTWARE. |
1463 |
-*******************************************************************************/ |
1464 |
- |
1465 |
-#ifndef __KQUEUE_SUB_H |
1466 |
-#define __KQUEUE_SUB_H |
1467 |
- |
1468 |
-#include "dep-list.h" |
1469 |
- |
1470 |
-/** |
1471 |
- * kqueue_sub: |
1472 |
- * @filename: a name of the file to monitor |
1473 |
- * @user_data: the pointer to user data |
1474 |
- * @pair_moves: unused (currently not implemented) |
1475 |
- * @fd: the associated file descriptor (used by kqueue) |
1476 |
- * |
1477 |
- * Represents a subscription on a file or directory. |
1478 |
- */ |
1479 |
-typedef struct |
1480 |
-{ |
1481 |
- gchar* filename; |
1482 |
- gpointer user_data; |
1483 |
- gboolean pair_moves; |
1484 |
- int fd; |
1485 |
- dep_list* deps; |
1486 |
- int is_dir; |
1487 |
-} kqueue_sub; |
1488 |
- |
1489 |
-kqueue_sub* _kh_sub_new (const gchar* filename, gboolean pair_moves, gpointer user_data); |
1490 |
-void _kh_sub_free (kqueue_sub* sub); |
1491 |
- |
1492 |
-#endif /* __KQUEUE_SUB_H */ |
1493 |
diff --git gio/kqueue/kqueue-thread.c gio/kqueue/kqueue-thread.c |
1494 |
deleted file mode 100644 |
1495 |
index 642b997db..000000000 |
1496 |
--- gio/kqueue/kqueue-thread.c |
1497 |
+++ /dev/null |
1498 |
@@ -1,304 +0,0 @@ |
1499 |
-/******************************************************************************* |
1500 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1501 |
- |
1502 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1503 |
- of this software and associated documentation files (the "Software"), to deal |
1504 |
- in the Software without restriction, including without limitation the rights |
1505 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1506 |
- copies of the Software, and to permit persons to whom the Software is |
1507 |
- furnished to do so, subject to the following conditions: |
1508 |
- |
1509 |
- The above copyright notice and this permission notice shall be included in |
1510 |
- all copies or substantial portions of the Software. |
1511 |
- |
1512 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1513 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1514 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1515 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1516 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1517 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1518 |
- THE SOFTWARE. |
1519 |
-*******************************************************************************/ |
1520 |
- |
1521 |
-#include "config.h" |
1522 |
-#include <sys/types.h> |
1523 |
-#include <sys/event.h> |
1524 |
-#include <sys/time.h> |
1525 |
-#include <unistd.h> |
1526 |
-#include <errno.h> |
1527 |
-#include <glib.h> |
1528 |
- |
1529 |
-#include "kqueue-thread.h" |
1530 |
-#include "kqueue-sub.h" |
1531 |
-#include "kqueue-utils.h" |
1532 |
- |
1533 |
-static gboolean kt_debug_enabled = FALSE; |
1534 |
-#define KT_W if (kt_debug_enabled) g_warning |
1535 |
- |
1536 |
-static GQueue pick_up_fds_queue = G_QUEUE_INIT; |
1537 |
-G_LOCK_DEFINE_STATIC (pick_up_lock); |
1538 |
- |
1539 |
-static GSList *remove_fds_list = NULL; |
1540 |
-G_LOCK_DEFINE_STATIC (remove_lock); |
1541 |
- |
1542 |
-/* GIO does not have analogues for NOTE_LINK and(?) NOTE_REVOKE, so |
1543 |
- * we do not ask kqueue() to watch for these events for now. */ |
1544 |
-const uint32_t KQUEUE_VNODE_FLAGS = |
1545 |
- NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME; |
1546 |
- |
1547 |
-extern int get_kqueue_descriptor(void); |
1548 |
- |
1549 |
-/** |
1550 |
- * _kqueue_thread_collect_fds: |
1551 |
- * @events: a #kevents - the list of events to monitor. Will be extended |
1552 |
- * with new items. |
1553 |
- * |
1554 |
- * Picks up new file descriptors for monitoring from a global queue. |
1555 |
- * |
1556 |
- * To add new items to the list, use _kqueue_thread_push_fd(). |
1557 |
- */ |
1558 |
-static void |
1559 |
-_kqueue_thread_collect_fds (kevents *events) |
1560 |
-{ |
1561 |
- g_assert (events != NULL); |
1562 |
- gint length = 0; |
1563 |
- |
1564 |
- G_LOCK (pick_up_lock); |
1565 |
- if ((length = g_queue_get_length (&pick_up_fds_queue)) != 0) |
1566 |
- { |
1567 |
- gpointer fdp = NULL; |
1568 |
- kevents_extend_sz (events, length); |
1569 |
- |
1570 |
- while ((fdp = g_queue_pop_head (&pick_up_fds_queue)) != NULL) |
1571 |
- { |
1572 |
- struct kevent *pevent = &events->memory[events->kq_size++]; |
1573 |
- EV_SET (pevent, |
1574 |
- GPOINTER_TO_INT (fdp), |
1575 |
- EVFILT_VNODE, |
1576 |
- EV_ADD | EV_ENABLE | EV_ONESHOT, |
1577 |
- KQUEUE_VNODE_FLAGS, |
1578 |
- 0, |
1579 |
- 0); |
1580 |
- } |
1581 |
- } |
1582 |
- G_UNLOCK (pick_up_lock); |
1583 |
-} |
1584 |
- |
1585 |
- |
1586 |
-/** |
1587 |
- * _kqueue_thread_cleanup_fds: |
1588 |
- * @events: a #kevents -- list of events to monitor. Cancelled |
1589 |
- * subscriptions will be removed from it, and its size |
1590 |
- * probably will be reduced. |
1591 |
- * |
1592 |
- * Removes file descriptors from monitoring. |
1593 |
- * |
1594 |
- * This function will pick up file descriptors from a global list |
1595 |
- * to cancel monitoring on them. The list will be freed then. |
1596 |
- * |
1597 |
- * To add new items to the list, use _kqueue_thread_remove_fd(). |
1598 |
- */ |
1599 |
-static void |
1600 |
-_kqueue_thread_cleanup_fds (kevents *events) |
1601 |
-{ |
1602 |
- g_assert (events != NULL); |
1603 |
- |
1604 |
- G_LOCK (remove_lock); |
1605 |
- if (remove_fds_list) |
1606 |
- { |
1607 |
- size_t oldsize = events->kq_size; |
1608 |
- int i, j; |
1609 |
- |
1610 |
- for (i = 1, j = 1; i < oldsize; i++) |
1611 |
- { |
1612 |
- int fd = events->memory[i].ident; |
1613 |
- GSList *elem = g_slist_find (remove_fds_list, GINT_TO_POINTER (fd)); |
1614 |
- if (elem == NULL) |
1615 |
- { |
1616 |
- if (i != j) |
1617 |
- events->memory[j] = events->memory[i]; |
1618 |
- ++j; |
1619 |
- } |
1620 |
- else if (close (fd) == -1) |
1621 |
- KT_W ("Failed to close fd %d, error %d", fd, errno); |
1622 |
- } |
1623 |
- |
1624 |
- KT_W ("FD Clean up complete, kq_size now %d\n", j); |
1625 |
- events->kq_size = j; |
1626 |
- kevents_reduce (events); |
1627 |
- g_slist_free (remove_fds_list); |
1628 |
- remove_fds_list = NULL; |
1629 |
- } |
1630 |
- G_UNLOCK (remove_lock); |
1631 |
-} |
1632 |
- |
1633 |
- |
1634 |
-/** |
1635 |
- * _kqueue_thread_drop_fd: |
1636 |
- * @events: a #kevents -- list of events to monitor. Cancelled |
1637 |
- * subscriptions will be removed from it, and its size |
1638 |
- * probably will be reduced. |
1639 |
- * |
1640 |
- * Removes a concrete file descriptor from monitoring. |
1641 |
- */ |
1642 |
-static void |
1643 |
-_kqueue_thread_drop_fd (kevents *events, int fd) |
1644 |
-{ |
1645 |
- g_assert (events != NULL); |
1646 |
- |
1647 |
- int i; |
1648 |
- for (i = 1; i < events->kq_size; i++) |
1649 |
- { |
1650 |
- if (events->memory[i].ident == fd) |
1651 |
- { |
1652 |
- if (close (fd) == -1) |
1653 |
- KT_W ("Failed to close fd %d, error %d", fd, errno); |
1654 |
- |
1655 |
- events->memory[i] = events->memory[--events->kq_size]; |
1656 |
- return; |
1657 |
- } |
1658 |
- } |
1659 |
-} |
1660 |
- |
1661 |
-/** |
1662 |
- * _kqueue_thread_func: |
1663 |
- * @arg: a pointer to int -- control file descriptor. |
1664 |
- * |
1665 |
- * The thread communicates with the outside world through a so-called |
1666 |
- * command file descriptor. The thread reads control commands from it |
1667 |
- * and writes the notifications into it. |
1668 |
- * |
1669 |
- * Control commands are single-byte characters: |
1670 |
- * - 'A' - pick up new file descriptors to monitor |
1671 |
- * - 'R' - remove some descriptors from monitoring. |
1672 |
- * |
1673 |
- * For details, see _kqueue_thread_collect_fds() and |
1674 |
- * _kqueue_thread_cleanup_fds(). |
1675 |
- * |
1676 |
- * Notifications, that thread writes into the command file descriptor, |
1677 |
- * are represented with #kqueue_notification objects. |
1678 |
- * |
1679 |
- * Returns: %NULL |
1680 |
- */ |
1681 |
-void* |
1682 |
-_kqueue_thread_func (void *arg) |
1683 |
-{ |
1684 |
- int fd, kqueue_descriptor; |
1685 |
- kevents waiting; |
1686 |
- |
1687 |
- g_assert (arg != NULL); |
1688 |
- kevents_init_sz (&waiting, 1); |
1689 |
- |
1690 |
- fd = *(int *) arg; |
1691 |
- |
1692 |
- kqueue_descriptor = get_kqueue_descriptor(); |
1693 |
- if (kqueue_descriptor == -1) |
1694 |
- { |
1695 |
- KT_W ("fatal: kqueue is not initialized!\n"); |
1696 |
- return NULL; |
1697 |
- } |
1698 |
- |
1699 |
- EV_SET (&waiting.memory[0], |
1700 |
- fd, |
1701 |
- EVFILT_READ, |
1702 |
- EV_ADD | EV_ENABLE | EV_ONESHOT, |
1703 |
- NOTE_LOWAT, |
1704 |
- 1, |
1705 |
- 0); |
1706 |
- waiting.kq_size = 1; |
1707 |
- |
1708 |
- for (;;) |
1709 |
- { |
1710 |
- /* TODO: Provide more items in the 'eventlist' to kqueue(2). |
1711 |
- * Currently the backend takes notifications from the kernel one |
1712 |
- * by one, i.e. there will be a lot of system calls and context |
1713 |
- * switches when the application will monitor a lot of files with |
1714 |
- * high filesystem activity on each. */ |
1715 |
- |
1716 |
- struct kevent received; |
1717 |
- KT_W ("Watching for %zi items", waiting.kq_size); |
1718 |
- int ret = kevent (kqueue_descriptor, waiting.memory, waiting.kq_size, &received, 1, NULL); |
1719 |
- int kevent_errno = errno; |
1720 |
- KT_W ("Awoken."); |
1721 |
- |
1722 |
- if (ret == -1) |
1723 |
- { |
1724 |
- KT_W ("kevent failed: %d", kevent_errno); |
1725 |
- if (kevent_errno == EINTR) |
1726 |
- continue; |
1727 |
- else |
1728 |
- return NULL; |
1729 |
- } |
1730 |
- |
1731 |
- if (received.ident == fd) |
1732 |
- { |
1733 |
- char c; |
1734 |
- if (!_ku_read (fd, &c, 1)) |
1735 |
- { |
1736 |
- KT_W ("Failed to read command, error %d", errno); |
1737 |
- continue; |
1738 |
- } |
1739 |
- if (c == 'A') |
1740 |
- _kqueue_thread_collect_fds (&waiting); |
1741 |
- else if (c == 'R') |
1742 |
- _kqueue_thread_cleanup_fds (&waiting); |
1743 |
- } |
1744 |
- else |
1745 |
- { |
1746 |
- struct kqueue_notification kn; |
1747 |
- kn.fd = received.ident; |
1748 |
- |
1749 |
- if (received.flags & EV_ERROR) |
1750 |
- { |
1751 |
- kn.flags = NOTE_REVOKE; |
1752 |
- _kqueue_thread_drop_fd (&waiting, received.ident); |
1753 |
- } |
1754 |
- else |
1755 |
- kn.flags = (received.fflags & ~NOTE_REVOKE); |
1756 |
- |
1757 |
- if (!_ku_write (fd, &kn, sizeof (struct kqueue_notification))) |
1758 |
- KT_W ("Failed to write a kqueue notification, error %d", errno); |
1759 |
- } |
1760 |
- } |
1761 |
- kevents_free (&waiting); |
1762 |
- return NULL; |
1763 |
-} |
1764 |
- |
1765 |
- |
1766 |
-/** |
1767 |
- * _kqueue_thread_push_fd: |
1768 |
- * @fd: a file descriptor |
1769 |
- * |
1770 |
- * Puts a new file descriptor into the pick up list for monitroing. |
1771 |
- * |
1772 |
- * The kqueue thread will not start monitoring on it immediately, it |
1773 |
- * should be bumped via its command file descriptor manually. |
1774 |
- * See kqueue_thread() and _kqueue_thread_collect_fds() for details. |
1775 |
- */ |
1776 |
-void |
1777 |
-_kqueue_thread_push_fd (int fd) |
1778 |
-{ |
1779 |
- G_LOCK (pick_up_lock); |
1780 |
- g_queue_push_tail (&pick_up_fds_queue, GINT_TO_POINTER (fd)); |
1781 |
- G_UNLOCK (pick_up_lock); |
1782 |
-} |
1783 |
- |
1784 |
- |
1785 |
-/** |
1786 |
- * _kqueue_thread_remove_fd: |
1787 |
- * @fd: a file descriptor |
1788 |
- * |
1789 |
- * Puts a new file descriptor into the remove list to cancel monitoring |
1790 |
- * on it. |
1791 |
- * |
1792 |
- * The kqueue thread will not stop monitoring on it immediately, it |
1793 |
- * should be bumped via its command file descriptor manually. |
1794 |
- * See kqueue_thread() and _kqueue_thread_collect_fds() for details. |
1795 |
- */ |
1796 |
-void |
1797 |
-_kqueue_thread_remove_fd (int fd) |
1798 |
-{ |
1799 |
- G_LOCK (remove_lock); |
1800 |
- remove_fds_list = g_slist_prepend (remove_fds_list, GINT_TO_POINTER (fd)); |
1801 |
- G_UNLOCK (remove_lock); |
1802 |
-} |
1803 |
diff --git gio/kqueue/kqueue-thread.h gio/kqueue/kqueue-thread.h |
1804 |
deleted file mode 100644 |
1805 |
index 0e46a0d69..000000000 |
1806 |
--- gio/kqueue/kqueue-thread.h |
1807 |
+++ /dev/null |
1808 |
@@ -1,45 +0,0 @@ |
1809 |
-/******************************************************************************* |
1810 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1811 |
- |
1812 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1813 |
- of this software and associated documentation files (the "Software"), to deal |
1814 |
- in the Software without restriction, including without limitation the rights |
1815 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1816 |
- copies of the Software, and to permit persons to whom the Software is |
1817 |
- furnished to do so, subject to the following conditions: |
1818 |
- |
1819 |
- The above copyright notice and this permission notice shall be included in |
1820 |
- all copies or substantial portions of the Software. |
1821 |
- |
1822 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1823 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1824 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1825 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1826 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1827 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1828 |
- THE SOFTWARE. |
1829 |
-*******************************************************************************/ |
1830 |
- |
1831 |
-#ifndef __KQUEUE_THREAD_H |
1832 |
-#define __KQUEUE_THREAD_H |
1833 |
- |
1834 |
-/** |
1835 |
- * kqueue_notification: |
1836 |
- * @fd: file descriptor, on which an activity has occured. |
1837 |
- * @flags: kqueue event flags, see man kevent(2). |
1838 |
- * |
1839 |
- * Represents an event occured on a file descriptor. Used for marshalling from |
1840 |
- * kqueue thread to its subscribers. |
1841 |
- */ |
1842 |
-struct kqueue_notification { |
1843 |
- /*< public >*/ |
1844 |
- int fd; |
1845 |
- uint32_t flags; |
1846 |
-}; |
1847 |
- |
1848 |
- |
1849 |
-void* _kqueue_thread_func (void *arg); |
1850 |
-void _kqueue_thread_push_fd (int fd); |
1851 |
-void _kqueue_thread_remove_fd (int fd); |
1852 |
- |
1853 |
-#endif /* __KQUEUE_SUB_H */ |
1854 |
diff --git gio/kqueue/kqueue-utils.c gio/kqueue/kqueue-utils.c |
1855 |
deleted file mode 100644 |
1856 |
index bba652278..000000000 |
1857 |
--- gio/kqueue/kqueue-utils.c |
1858 |
+++ /dev/null |
1859 |
@@ -1,210 +0,0 @@ |
1860 |
-/******************************************************************************* |
1861 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
1862 |
- |
1863 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
1864 |
- of this software and associated documentation files (the "Software"), to deal |
1865 |
- in the Software without restriction, including without limitation the rights |
1866 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
1867 |
- copies of the Software, and to permit persons to whom the Software is |
1868 |
- furnished to do so, subject to the following conditions: |
1869 |
- |
1870 |
- The above copyright notice and this permission notice shall be included in |
1871 |
- all copies or substantial portions of the Software. |
1872 |
- |
1873 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
1874 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
1875 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
1876 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
1877 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
1878 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
1879 |
- THE SOFTWARE. |
1880 |
-*******************************************************************************/ |
1881 |
- |
1882 |
-#include <sys/types.h> |
1883 |
-#include <sys/event.h> |
1884 |
-#include <string.h> |
1885 |
-#include <glib.h> |
1886 |
-#include <unistd.h> |
1887 |
-#include <sys/stat.h> |
1888 |
-#include <errno.h> |
1889 |
-#include "kqueue-utils.h" |
1890 |
- |
1891 |
-static gboolean ku_debug_enabled = FALSE; |
1892 |
-#define KU_W if (ku_debug_enabled) g_warning |
1893 |
- |
1894 |
- |
1895 |
- |
1896 |
-#define KEVENTS_EXTEND_COUNT 10 |
1897 |
- |
1898 |
- |
1899 |
-/** |
1900 |
- * kevents_init_sz: |
1901 |
- * @kv: a #kevents |
1902 |
- * @n_initial: the initial preallocated memory size. If it is less than |
1903 |
- * %KEVENTS_EXTEND_COUNT, this value will be used instead. |
1904 |
- * |
1905 |
- * Initializes a #kevents object. |
1906 |
- **/ |
1907 |
-void |
1908 |
-kevents_init_sz (kevents *kv, gsize n_initial) |
1909 |
-{ |
1910 |
- g_assert (kv != NULL); |
1911 |
- |
1912 |
- memset (kv, 0, sizeof (kevents)); |
1913 |
- |
1914 |
- if (n_initial < KEVENTS_EXTEND_COUNT) |
1915 |
- n_initial = KEVENTS_EXTEND_COUNT; |
1916 |
- |
1917 |
- kv->memory = g_new0 (struct kevent, n_initial); |
1918 |
- kv->kq_allocated = n_initial; |
1919 |
-} |
1920 |
- |
1921 |
- |
1922 |
-/** |
1923 |
- * kevents_extend_sz: |
1924 |
- * @kv: a #kevents |
1925 |
- * @n_new: the number of new objects to be added |
1926 |
- * |
1927 |
- * Extends the allocated memory, if needed. |
1928 |
- **/ |
1929 |
-void |
1930 |
-kevents_extend_sz (kevents *kv, gsize n_new) |
1931 |
-{ |
1932 |
- g_assert (kv != NULL); |
1933 |
- |
1934 |
- if (kv->kq_size + n_new <= kv->kq_allocated) |
1935 |
- return; |
1936 |
- |
1937 |
- kv->kq_allocated += (n_new + KEVENTS_EXTEND_COUNT); |
1938 |
- kv->memory = g_renew (struct kevent, kv->memory, kv->kq_allocated); |
1939 |
-} |
1940 |
- |
1941 |
- |
1942 |
-/** |
1943 |
- * kevents_reduce: |
1944 |
- * @kv: a #kevents |
1945 |
- * |
1946 |
- * Reduces the allocated heap size, if needed. |
1947 |
- * |
1948 |
- * If the allocated heap size is >= 3*used |
1949 |
- * and 2*used >= %KEVENTS_EXTEND_COUNT, reduce it to 2*used. |
1950 |
- **/ |
1951 |
-void |
1952 |
-kevents_reduce (kevents *kv) |
1953 |
-{ |
1954 |
- g_assert (kv != NULL); |
1955 |
- gsize candidate_sz; |
1956 |
- |
1957 |
- if (kv->kq_size == 0 || kv->kq_allocated == 0 || kv->memory == NULL) |
1958 |
- return; |
1959 |
- |
1960 |
- candidate_sz = 2 * kv->kq_size; |
1961 |
- |
1962 |
- if (((double) kv->kq_allocated / kv->kq_size) >= 3 && |
1963 |
- candidate_sz >= KEVENTS_EXTEND_COUNT) |
1964 |
- { |
1965 |
- kv->kq_allocated = candidate_sz; |
1966 |
- kv->memory = g_renew (struct kevent, kv->memory, kv->kq_allocated); |
1967 |
- } |
1968 |
-} |
1969 |
- |
1970 |
- |
1971 |
-/** |
1972 |
- * kevents_free: |
1973 |
- * @kv: a #kevents |
1974 |
- * |
1975 |
- * Resets the kevents object and frees all the associated memory. |
1976 |
- **/ |
1977 |
-void |
1978 |
-kevents_free (kevents *kv) |
1979 |
-{ |
1980 |
- g_assert (kv != NULL); |
1981 |
- |
1982 |
- g_free (kv->memory); |
1983 |
- memset (kv, 0, sizeof (kevents)); |
1984 |
-} |
1985 |
- |
1986 |
- |
1987 |
-#define SAFE_GENERIC_OP(fcn, fd, data, size) \ |
1988 |
- while (size > 0) \ |
1989 |
- { \ |
1990 |
- gsize retval = fcn (fd, data, size); \ |
1991 |
- if (retval == -1) \ |
1992 |
- { \ |
1993 |
- if (errno == EINTR) \ |
1994 |
- continue; \ |
1995 |
- else \ |
1996 |
- return FALSE; \ |
1997 |
- } \ |
1998 |
- size -= retval; \ |
1999 |
- data += retval; \ |
2000 |
- } \ |
2001 |
- return TRUE; |
2002 |
- |
2003 |
- |
2004 |
-/** |
2005 |
- * _ku_read: |
2006 |
- * @fd: a file descriptor |
2007 |
- * @data: the destination buffer |
2008 |
- * @size: how many bytes to read |
2009 |
- * |
2010 |
- * A ready-to-EINTR version of read(). |
2011 |
- * |
2012 |
- * This function expects to work with a blocking socket. |
2013 |
- * |
2014 |
- * Returns: %TRUE on success, %FALSE otherwise |
2015 |
- **/ |
2016 |
-gboolean |
2017 |
-_ku_read (int fd, gpointer data, gsize size) |
2018 |
-{ |
2019 |
- SAFE_GENERIC_OP (read, fd, data, size); |
2020 |
-} |
2021 |
- |
2022 |
- |
2023 |
-/** |
2024 |
- * _ku_write: |
2025 |
- * @fd: a file descriptor |
2026 |
- * @data: the buffer to write |
2027 |
- * @size: how many bytes to write |
2028 |
- * |
2029 |
- * A ready-to-EINTR version of write(). |
2030 |
- * |
2031 |
- * This function expects to work with a blocking socket. |
2032 |
- * |
2033 |
- * Returns: %TRUE on success, %FALSE otherwise |
2034 |
- **/ |
2035 |
-gboolean |
2036 |
-_ku_write (int fd, gconstpointer data, gsize size) |
2037 |
-{ |
2038 |
- SAFE_GENERIC_OP (write, fd, data, size); |
2039 |
-} |
2040 |
- |
2041 |
- |
2042 |
-/** |
2043 |
- * Get some file information by its file descriptor. |
2044 |
- * |
2045 |
- * @param[in] fd A file descriptor. |
2046 |
- * @param[out] is_dir A flag indicating directory. |
2047 |
- * @param[out] inode A file's inode number. |
2048 |
- **/ |
2049 |
-void |
2050 |
-_ku_file_information (int fd, int *is_dir, ino_t *inode) |
2051 |
-{ |
2052 |
- g_assert (fd != -1); |
2053 |
- |
2054 |
- struct stat st; |
2055 |
- memset (&st, 0, sizeof (struct stat)); |
2056 |
- |
2057 |
- if (fstat (fd, &st) == -1) |
2058 |
- { |
2059 |
- KU_W ("fstat failed, assuming it is just a file"); |
2060 |
- is_dir = NULL; |
2061 |
- return; |
2062 |
- } |
2063 |
- |
2064 |
- if (is_dir != NULL) |
2065 |
- *is_dir = ((st.st_mode & S_IFDIR) == S_IFDIR) ? 1 : 0; |
2066 |
- |
2067 |
- if (inode != NULL) |
2068 |
- *inode = st.st_ino; |
2069 |
-} |
2070 |
diff --git gio/kqueue/kqueue-utils.h gio/kqueue/kqueue-utils.h |
2071 |
deleted file mode 100644 |
2072 |
index 4e37f4a99..000000000 |
2073 |
--- gio/kqueue/kqueue-utils.h |
2074 |
+++ /dev/null |
2075 |
@@ -1,53 +0,0 @@ |
2076 |
-/******************************************************************************* |
2077 |
- Copyright (c) 2011, 2012 Dmitry Matveev <me@dmitrymatveev.co.uk> |
2078 |
- |
2079 |
- Permission is hereby granted, free of charge, to any person obtaining a copy |
2080 |
- of this software and associated documentation files (the "Software"), to deal |
2081 |
- in the Software without restriction, including without limitation the rights |
2082 |
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
2083 |
- copies of the Software, and to permit persons to whom the Software is |
2084 |
- furnished to do so, subject to the following conditions: |
2085 |
- |
2086 |
- The above copyright notice and this permission notice shall be included in |
2087 |
- all copies or substantial portions of the Software. |
2088 |
- |
2089 |
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
2090 |
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
2091 |
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
2092 |
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
2093 |
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
2094 |
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
2095 |
- THE SOFTWARE. |
2096 |
-*******************************************************************************/ |
2097 |
- |
2098 |
-#ifndef __KQUEUE_UTILS_H |
2099 |
-#define __KQUEUE_UTILS_H |
2100 |
- |
2101 |
-#include <sys/types.h> /* ino_t */ |
2102 |
- |
2103 |
-/** |
2104 |
- * kqueue_notification: |
2105 |
- * @memory: a pointer to the allocated memory |
2106 |
- * @kq_size: the number of used items |
2107 |
- * @kq_allocated: the number of allocated items |
2108 |
- * |
2109 |
- * Represents a pool of (struct kevent) objects. |
2110 |
- */ |
2111 |
-typedef struct { |
2112 |
- struct kevent *memory; |
2113 |
- gsize kq_size; |
2114 |
- gsize kq_allocated; |
2115 |
-} kevents; |
2116 |
- |
2117 |
-void kevents_init_sz (kevents *kv, gsize n_initial); |
2118 |
-void kevents_extend_sz (kevents *kv, gsize n_new); |
2119 |
-void kevents_reduce (kevents *kv); |
2120 |
-void kevents_free (kevents *kv); |
2121 |
- |
2122 |
- |
2123 |
-gboolean _ku_read (int fd, gpointer data, gsize size); |
2124 |
-gboolean _ku_write (int fd, gconstpointer data, gsize size); |
2125 |
- |
2126 |
-void _ku_file_information (int fd, int *is_dir, ino_t *inode); |
2127 |
- |
2128 |
-#endif /* __KQUEUE_UTILS_H */ |
2129 |
commit e962adbf42f8b0721d74c2d78faea3c377ec03ae |
2130 |
Author: Ting-Wei Lan <lantw@src.gnome.org> |
2131 |
Date: Tue Mar 20 21:58:20 2018 +0800 |
2132 |
|
2133 |
gpollfilemonitor: Fix use-after-free caused by leaking GSource |
2134 |
|
2135 |
https://bugzilla.gnome.org/show_bug.cgi?id=794528 |
2136 |
|
2137 |
diff --git gio/gpollfilemonitor.c gio/gpollfilemonitor.c |
2138 |
index 411e00393..bd3d78a02 100644 |
2139 |
--- gio/gpollfilemonitor.c |
2140 |
+++ gio/gpollfilemonitor.c |
2141 |
@@ -50,7 +50,9 @@ g_poll_file_monitor_finalize (GObject* object) |
2142 |
|
2143 |
poll_monitor = G_POLL_FILE_MONITOR (object); |
2144 |
|
2145 |
+ g_poll_file_monitor_cancel (G_FILE_MONITOR (poll_monitor)); |
2146 |
g_object_unref (poll_monitor->file); |
2147 |
+ g_clear_object (&poll_monitor->last_info); |
2148 |
|
2149 |
G_OBJECT_CLASS (g_poll_file_monitor_parent_class)->finalize (object); |
2150 |
} |