From 170ed29b438ed0d9f31f1cd1f2f6d9808540763d Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 22 Sep 2015 08:40:08 +0200 Subject: [PATCH] Implement gfile-valid-p * lisp/filenotify.el (file-notify-callback): Fix typo. (gfile-valid-p): Remove defalias. * src/gfilenotify.c (dir_monitor_callback): Cancel the monitor if the file or directory to be watched is deleted. (Fgfile_add_watch): Make watch_object a triple. (Fgfile_rm_watch): Check, whether watch is cancelled already. (Fgfile_valid_p): New defun. (syms_of_gfilenotify): Declare Sgfile_valid_p. --- lisp/filenotify.el | 5 +---- src/gfilenotify.c | 45 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lisp/filenotify.el b/lisp/filenotify.el index b3490fd3ebb..e2c0af0d1b7 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -161,7 +161,7 @@ EVENT is the cadr of the event in `file-notify-handle-event' ((eq action 'attrib) 'attribute-changed) ((memq action '(create added)) 'created) ((memq action '(modify modified)) 'changed) - ((memq action '(delete 'delete-self move-self removed)) 'deleted) + ((memq action '(delete delete-self move-self removed)) 'deleted) ;; Make the event pending. ((memq action '(moved-from renamed-from)) (setq file-notify--pending-event @@ -359,9 +359,6 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." desc)) (file-notify-error nil)))))) -;; Temporary declarations. -(defalias 'gfile-valid-p 'identity) - (defun file-notify-valid-p (descriptor) "Check a watch specified by its DESCRIPTOR. DESCRIPTOR should be an object returned by `file-notify-add-watch'." diff --git a/src/gfilenotify.c b/src/gfilenotify.c index 5c6ebe65d87..1439666f5f8 100644 --- a/src/gfilenotify.c +++ b/src/gfilenotify.c @@ -29,6 +29,7 @@ along with GNU Emacs. If not, see . */ #include "process.h" +/* This is a list, elements are triples (DESCRIPTOR FILE CALLBACK) */ static Lisp_Object watch_list; /* This is the callback function for arriving signals from @@ -93,10 +94,17 @@ dir_monitor_callback (GFileMonitor *monitor, Fcons (symbol, Fcons (build_string (name), otail))), - XCDR (watch_object)); + XCAR (XCDR (XCDR (watch_object)))); /* Store it into the input event queue. */ kbd_buffer_store_event (&event); + + /* Cancel monitor if file or directory is deleted. */ + if (((event_type == G_FILE_MONITOR_EVENT_DELETED) || + (event_type == G_FILE_MONITOR_EVENT_MOVED)) && + (strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0) && + (!g_file_monitor_is_cancelled (monitor))) + g_file_monitor_cancel (monitor); } /* Cleanup. */ @@ -198,13 +206,13 @@ will be reported only in case of the `moved' event. */) (GCallback) dir_monitor_callback, NULL); /* Store watch object in watch list. */ - watch_object = Fcons (watch_descriptor, callback); + watch_object = list3 (watch_descriptor, file, callback); watch_list = Fcons (watch_object, watch_list); return watch_descriptor; } -DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, +DEFUN ("gfile-rm-watc", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, doc: /* Remove an existing WATCH-DESCRIPTOR. WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) @@ -218,11 +226,12 @@ WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) eassert (INTEGERP (watch_descriptor)); GFileMonitor *monitor = XINTPTR (watch_descriptor); - if (!g_file_monitor_cancel (monitor)) - xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"), - watch_descriptor); + if (!g_file_monitor_is_cancelled (monitor) && + !g_file_monitor_cancel (monitor)) + 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); /* Cleanup. */ @@ -231,6 +240,27 @@ WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) return Qt; } +DEFUN ("gfile-valid-p", Fgfile_valid_p, Sgfile_valid_p, 1, 1, 0, + doc: /* "Check a watch specified by its WATCH-DESCRIPTOR. + +WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. + +A watch can become invalid if the file or directory it watches is +deleted, or if the watcher thread exits abnormally for any other +reason. Removing the watch by calling `gfile-rm-watch' also makes it +invalid. */) + (Lisp_Object watch_descriptor) +{ + Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list); + if (NILP (watch_object)) + return Qnil; + else + { + GFileMonitor *monitor = XINTPTR (watch_descriptor); + return g_file_monitor_is_cancelled (monitor) ? Qnil : Qt; + } +} + void globals_of_gfilenotify (void) @@ -246,6 +276,7 @@ syms_of_gfilenotify (void) { defsubr (&Sgfile_add_watch); defsubr (&Sgfile_rm_watch); + defsubr (&Sgfile_valid_p); /* Filter objects. */ DEFSYM (Qwatch_mounts, "watch-mounts"); /* G_FILE_MONITOR_WATCH_MOUNTS */ -- 2.39.2