aboutsummaryrefslogtreecommitdiffstats
path: root/src/kqueue.c
diff options
context:
space:
mode:
authorMichael Albinus2015-11-11 09:22:06 +0100
committerMichael Albinus2015-11-25 15:07:11 +0100
commite0a68f25877c9b2497d7c4ad0aa1b69e34a3b11f (patch)
tree0e8ef95ac11a1ad0b4869b1e43978e1343b65182 /src/kqueue.c
parent7543d1cf46e475bd14a147ef676abe3935a8f96e (diff)
downloademacs-e0a68f25877c9b2497d7c4ad0aa1b69e34a3b11f.tar.gz
emacs-e0a68f25877c9b2497d7c4ad0aa1b69e34a3b11f.zip
Continue kqueue implementation
* lisp/filenotify.el (file-notify-handle-event) (file-notify-callback): Enable trace messages. * src/kqueue.c: Include also <sys/types.h>. (kqueue_callback): Remove watch in case of NOTE_DELETE or NOTE_RENAME. (Fkqueue_rm_watch, Fkqueue_valid_p): New functions. (syms_of_kqueue): Add them.
Diffstat (limited to 'src/kqueue.c')
-rw-r--r--src/kqueue.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/src/kqueue.c b/src/kqueue.c
index a4c3892e9f2..c2e859f8db9 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21#ifdef HAVE_KQUEUE 21#ifdef HAVE_KQUEUE
22#include <stdio.h> 22#include <stdio.h>
23#include <sys/types.h>
23#include <sys/event.h> 24#include <sys/event.h>
24#include <sys/file.h> 25#include <sys/file.h>
25#include "lisp.h" 26#include "lisp.h"
@@ -41,9 +42,9 @@ kqueue_callback (int fd, void *data)
41 for (;;) { 42 for (;;) {
42 struct kevent kev; 43 struct kevent kev;
43 struct input_event event; 44 struct input_event event;
44 Lisp_Object monitor_object, watch_object, name, callback, actions; 45 Lisp_Object monitor_object, watch_object, file, callback, actions;
45 46
46 static const struct timespec nullts = { 0, 0 }; 47 /* Read one event. */
47 int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL); 48 int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL);
48 if (ret < 1) { 49 if (ret < 1) {
49 /* All events read. */ 50 /* All events read. */
@@ -55,7 +56,7 @@ kqueue_callback (int fd, void *data)
55 watch_object = assq_no_quit (monitor_object, watch_list); 56 watch_object = assq_no_quit (monitor_object, watch_list);
56 57
57 if (CONSP (watch_object)) { 58 if (CONSP (watch_object)) {
58 name = XCAR (XCDR (watch_object)); 59 file = XCAR (XCDR (watch_object));
59 callback = XCAR (XCDR (XCDR (XCDR (watch_object)))); 60 callback = XCAR (XCDR (XCDR (XCDR (watch_object))));
60 } 61 }
61 else 62 else
@@ -76,13 +77,13 @@ kqueue_callback (int fd, void *data)
76 if (kev.fflags & NOTE_RENAME) 77 if (kev.fflags & NOTE_RENAME)
77 actions = Fcons (Qrename, actions); 78 actions = Fcons (Qrename, actions);
78 79
79 if (!NILP (actions)) { 80 if (! NILP (actions)) {
80 /* Construct an event. */ 81 /* Construct an event. */
81 EVENT_INIT (event); 82 EVENT_INIT (event);
82 event.kind = FILE_NOTIFY_EVENT; 83 event.kind = FILE_NOTIFY_EVENT;
83 event.frame_or_window = Qnil; 84 event.frame_or_window = Qnil;
84 event.arg = list2 (Fcons (monitor_object, 85 event.arg = list2 (Fcons (monitor_object,
85 Fcons (actions, Fcons (name, Qnil))), 86 Fcons (actions, Fcons (file, Qnil))),
86 callback); 87 callback);
87 88
88 /* Store it into the input event queue. */ 89 /* Store it into the input event queue. */
@@ -90,7 +91,8 @@ kqueue_callback (int fd, void *data)
90 } 91 }
91 92
92 /* Cancel monitor if file or directory is deleted. */ 93 /* Cancel monitor if file or directory is deleted. */
93 /* TODO: Implement it. */ 94 if (kev.fflags & (NOTE_DELETE | NOTE_RENAME))
95 Fkqueue_rm_watch (monitor_object);
94 } 96 }
95 return; 97 return;
96} 98}
@@ -101,7 +103,7 @@ DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0,
101This arranges for filesystem events pertaining to FILE to be reported 103This arranges for filesystem events pertaining to FILE to be reported
102to Emacs. Use `kqueue-rm-watch' to cancel the watch. 104to Emacs. Use `kqueue-rm-watch' to cancel the watch.
103 105
104Value is a descriptor for the added watch. If the file cannot be 106Returned value is a descriptor for the added watch. If the file cannot be
105watched for some reason, this function signals a `file-notify-error' error. 107watched for some reason, this function signals a `file-notify-error' error.
106 108
107FLAGS is a list of events to be watched for. It can include the 109FLAGS is a list of events to be watched for. It can include the
@@ -138,12 +140,12 @@ will be reported only in case of the `rename' event. */)
138 report_file_error ("File does not exist", file); 140 report_file_error ("File does not exist", file);
139 141
140 /* TODO: Directories shall be supported as well. */ 142 /* TODO: Directories shall be supported as well. */
141 if (!NILP (Ffile_directory_p (file))) 143 if (! NILP (Ffile_directory_p (file)))
142 report_file_error ("Directory watching is not supported (yet)", file); 144 report_file_error ("Directory watching is not supported (yet)", file);
143 145
144 CHECK_LIST (flags); 146 CHECK_LIST (flags);
145 147
146 if (!FUNCTIONP (callback)) 148 if (! FUNCTIONP (callback))
147 wrong_type_argument (Qinvalid_function, callback); 149 wrong_type_argument (Qinvalid_function, callback);
148 150
149 if (kqueuefd < 0) 151 if (kqueuefd < 0)
@@ -166,16 +168,16 @@ will be reported only in case of the `rename' event. */)
166 report_file_error ("File cannot be opened", file); 168 report_file_error ("File cannot be opened", file);
167 169
168 /* Assemble filter flags */ 170 /* Assemble filter flags */
169 if (!NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE; 171 if (! NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE;
170 if (!NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE; 172 if (! NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE;
171 if (!NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND; 173 if (! NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND;
172 if (!NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB; 174 if (! NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB;
173 if (!NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK; 175 if (! NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK;
174 if (!NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME; 176 if (! NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME;
175 177
176 /* Register event. */ 178 /* Register event. */
177 EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 179 EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
178 fflags, 0, NULL); 180 fflags, 0, NULL);
179 181
180 if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0) 182 if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0)
181 report_file_error ("Cannot watch file", file); 183 report_file_error ("Cannot watch file", file);
@@ -188,7 +190,6 @@ will be reported only in case of the `rename' event. */)
188 return watch_descriptor; 190 return watch_descriptor;
189} 191}
190 192
191#if 0
192DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0, 193DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0,
193 doc: /* Remove an existing WATCH-DESCRIPTOR. 194 doc: /* Remove an existing WATCH-DESCRIPTOR.
194 195
@@ -202,42 +203,35 @@ WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'. */)
202 watch_descriptor); 203 watch_descriptor);
203 204
204 eassert (INTEGERP (watch_descriptor)); 205 eassert (INTEGERP (watch_descriptor));
205 GFileMonitor *monitor = XINTPTR (watch_descriptor); 206 int fd = XINT (watch_descriptor);
206 if (!g_file_monitor_is_cancelled (monitor) && 207 if ( fd >= 0)
207 !g_file_monitor_cancel (monitor)) 208 emacs_close (fd);
208 xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
209 watch_descriptor);
210 209
211 /* Remove watch descriptor from watch list. */ 210 /* Remove watch descriptor from watch list. */
212 watch_list = Fdelq (watch_object, watch_list); 211 watch_list = Fdelq (watch_object, watch_list);
213 212
214 /* Cleanup. */ 213 if (NILP (watch_list) && (kqueuefd >= 0)) {
215 g_object_unref (monitor); 214 delete_read_fd (kqueuefd);
215 emacs_close (kqueuefd);
216 kqueuefd = -1;
217 }
216 218
217 return Qt; 219 return Qt;
218} 220}
219 221
220DEFUN ("gfile-valid-p", Fgfile_valid_p, Sgfile_valid_p, 1, 1, 0, 222DEFUN ("kqueue-valid-p", Fkqueue_valid_p, Skqueue_valid_p, 1, 1, 0,
221 doc: /* "Check a watch specified by its WATCH-DESCRIPTOR. 223 doc: /* "Check a watch specified by its WATCH-DESCRIPTOR.
222 224
223WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. 225WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'.
224 226
225A watch can become invalid if the file or directory it watches is 227A watch can become invalid if the file or directory it watches is
226deleted, or if the watcher thread exits abnormally for any other 228deleted, or if the watcher thread exits abnormally for any other
227reason. Removing the watch by calling `gfile-rm-watch' also makes it 229reason. Removing the watch by calling `kqueue-rm-watch' also makes it
228invalid. */) 230invalid. */)
229 (Lisp_Object watch_descriptor) 231 (Lisp_Object watch_descriptor)
230{ 232{
231 Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list); 233 return NILP (assq_no_quit (watch_descriptor, watch_list)) ? Qnil : Qt;
232 if (NILP (watch_object))
233 return Qnil;
234 else
235 {
236 GFileMonitor *monitor = XINTPTR (watch_descriptor);
237 return g_file_monitor_is_cancelled (monitor) ? Qnil : Qt;
238 }
239} 234}
240#endif /* 0 */
241 235
242 236
243void 237void
@@ -250,8 +244,8 @@ void
250syms_of_kqueue (void) 244syms_of_kqueue (void)
251{ 245{
252 defsubr (&Skqueue_add_watch); 246 defsubr (&Skqueue_add_watch);
253 // defsubr (&Skqueue_rm_watch); 247 defsubr (&Skqueue_rm_watch);
254 // defsubr (&Skqueue_valid_p); 248 defsubr (&Skqueue_valid_p);
255 249
256 /* Event types. */ 250 /* Event types. */
257 DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */ 251 DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */
@@ -267,3 +261,11 @@ syms_of_kqueue (void)
267} 261}
268 262
269#endif /* HAVE_KQUEUE */ 263#endif /* HAVE_KQUEUE */
264
265/* TODO
266 * Implement watching directories.
267 * Add FILE1 in case of `rename'. */
268
269/* PROBLEMS
270 * https://bugs.launchpad.net/ubuntu/+source/libkqueue/+bug/1514837
271 prevents tests on Ubuntu. */