1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-05 19:31:02 -08:00

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.
This commit is contained in:
Michael Albinus 2015-11-11 09:22:06 +01:00
parent 7543d1cf46
commit e0a68f2587
2 changed files with 43 additions and 41 deletions

View file

@ -88,7 +88,7 @@ If EVENT is a filewatch event, call its callback. It has the format
Otherwise, signal a `file-notify-error'." Otherwise, signal a `file-notify-error'."
(interactive "e") (interactive "e")
;;(message "file-notify-handle-event %S" event) (message "file-notify-handle-event %S" event)
(if (and (eq (car event) 'file-notify) (if (and (eq (car event) 'file-notify)
(>= (length event) 3)) (>= (length event) 3))
(funcall (nth 2 event) (nth 1 event)) (funcall (nth 2 event) (nth 1 event))
@ -236,7 +236,7 @@ EVENT is the cadr of the event in `file-notify-handle-event'
(setq pending-event nil)) (setq pending-event nil))
;; Check for stopped. ;; Check for stopped.
;;(message "file-notify-callback %S %S" file registered) (message "file-notify-callback %S %S" file registered)
(setq (setq
stopped stopped
(or (or

View file

@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_KQUEUE #ifdef HAVE_KQUEUE
#include <stdio.h> #include <stdio.h>
#include <sys/types.h>
#include <sys/event.h> #include <sys/event.h>
#include <sys/file.h> #include <sys/file.h>
#include "lisp.h" #include "lisp.h"
@ -41,9 +42,9 @@ kqueue_callback (int fd, void *data)
for (;;) { for (;;) {
struct kevent kev; struct kevent kev;
struct input_event event; struct input_event event;
Lisp_Object monitor_object, watch_object, name, callback, actions; Lisp_Object monitor_object, watch_object, file, callback, actions;
static const struct timespec nullts = { 0, 0 }; /* Read one event. */
int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL); int ret = kevent (kqueuefd, NULL, 0, &kev, 1, NULL);
if (ret < 1) { if (ret < 1) {
/* All events read. */ /* All events read. */
@ -55,7 +56,7 @@ kqueue_callback (int fd, void *data)
watch_object = assq_no_quit (monitor_object, watch_list); watch_object = assq_no_quit (monitor_object, watch_list);
if (CONSP (watch_object)) { if (CONSP (watch_object)) {
name = XCAR (XCDR (watch_object)); file = XCAR (XCDR (watch_object));
callback = XCAR (XCDR (XCDR (XCDR (watch_object)))); callback = XCAR (XCDR (XCDR (XCDR (watch_object))));
} }
else else
@ -76,13 +77,13 @@ kqueue_callback (int fd, void *data)
if (kev.fflags & NOTE_RENAME) if (kev.fflags & NOTE_RENAME)
actions = Fcons (Qrename, actions); actions = Fcons (Qrename, actions);
if (!NILP (actions)) { if (! NILP (actions)) {
/* Construct an event. */ /* Construct an event. */
EVENT_INIT (event); EVENT_INIT (event);
event.kind = FILE_NOTIFY_EVENT; event.kind = FILE_NOTIFY_EVENT;
event.frame_or_window = Qnil; event.frame_or_window = Qnil;
event.arg = list2 (Fcons (monitor_object, event.arg = list2 (Fcons (monitor_object,
Fcons (actions, Fcons (name, Qnil))), Fcons (actions, Fcons (file, Qnil))),
callback); callback);
/* Store it into the input event queue. */ /* Store it into the input event queue. */
@ -90,7 +91,8 @@ kqueue_callback (int fd, void *data)
} }
/* Cancel monitor if file or directory is deleted. */ /* Cancel monitor if file or directory is deleted. */
/* TODO: Implement it. */ if (kev.fflags & (NOTE_DELETE | NOTE_RENAME))
Fkqueue_rm_watch (monitor_object);
} }
return; return;
} }
@ -101,7 +103,7 @@ DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_add_watch, 3, 3, 0,
This arranges for filesystem events pertaining to FILE to be reported This arranges for filesystem events pertaining to FILE to be reported
to Emacs. Use `kqueue-rm-watch' to cancel the watch. to Emacs. Use `kqueue-rm-watch' to cancel the watch.
Value is a descriptor for the added watch. If the file cannot be Returned value is a descriptor for the added watch. If the file cannot be
watched for some reason, this function signals a `file-notify-error' error. watched for some reason, this function signals a `file-notify-error' error.
FLAGS is a list of events to be watched for. It can include the FLAGS 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. */)
report_file_error ("File does not exist", file); report_file_error ("File does not exist", file);
/* TODO: Directories shall be supported as well. */ /* TODO: Directories shall be supported as well. */
if (!NILP (Ffile_directory_p (file))) if (! NILP (Ffile_directory_p (file)))
report_file_error ("Directory watching is not supported (yet)", file); report_file_error ("Directory watching is not supported (yet)", file);
CHECK_LIST (flags); CHECK_LIST (flags);
if (!FUNCTIONP (callback)) if (! FUNCTIONP (callback))
wrong_type_argument (Qinvalid_function, callback); wrong_type_argument (Qinvalid_function, callback);
if (kqueuefd < 0) if (kqueuefd < 0)
@ -166,16 +168,16 @@ will be reported only in case of the `rename' event. */)
report_file_error ("File cannot be opened", file); report_file_error ("File cannot be opened", file);
/* Assemble filter flags */ /* Assemble filter flags */
if (!NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE; if (! NILP (Fmember (Qdelete, flags))) fflags |= NOTE_DELETE;
if (!NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE; if (! NILP (Fmember (Qwrite, flags))) fflags |= NOTE_WRITE;
if (!NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND; if (! NILP (Fmember (Qextend, flags))) fflags |= NOTE_EXTEND;
if (!NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB; if (! NILP (Fmember (Qattrib, flags))) fflags |= NOTE_ATTRIB;
if (!NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK; if (! NILP (Fmember (Qlink, flags))) fflags |= NOTE_LINK;
if (!NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME; if (! NILP (Fmember (Qrename, flags))) fflags |= NOTE_RENAME;
/* Register event. */ /* Register event. */
EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, EV_SET (&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
fflags, 0, NULL); fflags, 0, NULL);
if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0) if (kevent (kqueuefd, &ev, 1, NULL, 0, NULL) < 0)
report_file_error ("Cannot watch file", file); report_file_error ("Cannot watch file", file);
@ -188,7 +190,6 @@ will be reported only in case of the `rename' event. */)
return watch_descriptor; return watch_descriptor;
} }
#if 0
DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0, DEFUN ("kqueue-rm-watch", Fkqueue_rm_watch, Skqueue_rm_watch, 1, 1, 0,
doc: /* Remove an existing WATCH-DESCRIPTOR. doc: /* Remove an existing WATCH-DESCRIPTOR.
@ -202,42 +203,35 @@ WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'. */)
watch_descriptor); watch_descriptor);
eassert (INTEGERP (watch_descriptor)); eassert (INTEGERP (watch_descriptor));
GFileMonitor *monitor = XINTPTR (watch_descriptor); int fd = XINT (watch_descriptor);
if (!g_file_monitor_is_cancelled (monitor) && if ( fd >= 0)
!g_file_monitor_cancel (monitor)) emacs_close (fd);
xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
watch_descriptor);
/* Remove watch descriptor from watch list. */ /* Remove watch descriptor from watch list. */
watch_list = Fdelq (watch_object, watch_list); watch_list = Fdelq (watch_object, watch_list);
/* Cleanup. */ if (NILP (watch_list) && (kqueuefd >= 0)) {
g_object_unref (monitor); delete_read_fd (kqueuefd);
emacs_close (kqueuefd);
kqueuefd = -1;
}
return Qt; return Qt;
} }
DEFUN ("gfile-valid-p", Fgfile_valid_p, Sgfile_valid_p, 1, 1, 0, DEFUN ("kqueue-valid-p", Fkqueue_valid_p, Skqueue_valid_p, 1, 1, 0,
doc: /* "Check a watch specified by its WATCH-DESCRIPTOR. doc: /* "Check a watch specified by its WATCH-DESCRIPTOR.
WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. WATCH-DESCRIPTOR should be an object returned by `kqueue-add-watch'.
A watch can become invalid if the file or directory it watches is A watch can become invalid if the file or directory it watches is
deleted, or if the watcher thread exits abnormally for any other deleted, or if the watcher thread exits abnormally for any other
reason. Removing the watch by calling `gfile-rm-watch' also makes it reason. Removing the watch by calling `kqueue-rm-watch' also makes it
invalid. */) invalid. */)
(Lisp_Object watch_descriptor) (Lisp_Object watch_descriptor)
{ {
Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list); return NILP (assq_no_quit (watch_descriptor, watch_list)) ? Qnil : Qt;
if (NILP (watch_object))
return Qnil;
else
{
GFileMonitor *monitor = XINTPTR (watch_descriptor);
return g_file_monitor_is_cancelled (monitor) ? Qnil : Qt;
}
} }
#endif /* 0 */
void void
@ -250,8 +244,8 @@ void
syms_of_kqueue (void) syms_of_kqueue (void)
{ {
defsubr (&Skqueue_add_watch); defsubr (&Skqueue_add_watch);
// defsubr (&Skqueue_rm_watch); defsubr (&Skqueue_rm_watch);
// defsubr (&Skqueue_valid_p); defsubr (&Skqueue_valid_p);
/* Event types. */ /* Event types. */
DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */ DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */
@ -267,3 +261,11 @@ syms_of_kqueue (void)
} }
#endif /* HAVE_KQUEUE */ #endif /* HAVE_KQUEUE */
/* TODO
* Implement watching directories.
* Add FILE1 in case of `rename'. */
/* PROBLEMS
* https://bugs.launchpad.net/ubuntu/+source/libkqueue/+bug/1514837
prevents tests on Ubuntu. */