diff options
| author | Michael Albinus | 2015-11-20 18:06:42 +0000 |
|---|---|---|
| committer | Michael Albinus | 2015-11-25 15:07:12 +0100 |
| commit | 0247489fed0f70b2abf960de48bc4432381a581b (patch) | |
| tree | 28e4de085d082377dfee71b800fff0b644cea3e1 /src/kqueue.c | |
| parent | 5154781141c2305c24103beb358453d30a838921 (diff) | |
| download | emacs-0247489fed0f70b2abf960de48bc4432381a581b.tar.gz emacs-0247489fed0f70b2abf960de48bc4432381a581b.zip | |
Rework file notifications, kqueue has problems with directory monitors
* lisp/filenotify.el (file-notify-add-watch): Call the native
add-watch function on the file, not on the dir.
* src/kqueue.c (kqueue_compare_dir_list): Make also bookkeeping
about already deleted entries.
* test/automated/auto-revert-tests.el
(auto-revert-test01-auto-revert-several-files): Do not call "cp -f"
since this deletes the target file first.
* test/automated/file-notify-tests.el (file-notify--test-event-test):
Make stronger checks.
(file-notify-test01-add-watch, file-notify-test02-events)
(file-notify-test04-file-validity, file-notify-test05-dir-validity):
Rewrite in order to call file monitors but directory monitors.
(file-notify-test06-many-events): Ler rename work in both directions.
Diffstat (limited to 'src/kqueue.c')
| -rw-r--r-- | src/kqueue.c | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/src/kqueue.c b/src/kqueue.c index ca0e3e7e1ca..1830040637e 100644 --- a/src/kqueue.c +++ b/src/kqueue.c | |||
| @@ -111,11 +111,12 @@ static void | |||
| 111 | kqueue_compare_dir_list | 111 | kqueue_compare_dir_list |
| 112 | (Lisp_Object watch_object) | 112 | (Lisp_Object watch_object) |
| 113 | { | 113 | { |
| 114 | Lisp_Object dir, pending_events; | 114 | Lisp_Object dir, pending_dl, deleted_dl; |
| 115 | Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl; | 115 | Lisp_Object old_directory_files, old_dl, new_directory_files, new_dl, dl; |
| 116 | 116 | ||
| 117 | dir = XCAR (XCDR (watch_object)); | 117 | dir = XCAR (XCDR (watch_object)); |
| 118 | pending_events = Qnil; | 118 | pending_dl = Qnil; |
| 119 | deleted_dl = Qnil; | ||
| 119 | 120 | ||
| 120 | old_directory_files = Fnth (make_number (4), watch_object); | 121 | old_directory_files = Fnth (make_number (4), watch_object); |
| 121 | old_dl = kqueue_directory_listing (old_directory_files); | 122 | old_dl = kqueue_directory_listing (old_directory_files); |
| @@ -168,6 +169,7 @@ kqueue_compare_dir_list | |||
| 168 | kqueue_generate_event | 169 | kqueue_generate_event |
| 169 | (watch_object, Fcons (Qrename, Qnil), | 170 | (watch_object, Fcons (Qrename, Qnil), |
| 170 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); | 171 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); |
| 172 | deleted_dl = Fcons (new_entry, deleted_dl); | ||
| 171 | } | 173 | } |
| 172 | new_dl = Fdelq (new_entry, new_dl); | 174 | new_dl = Fdelq (new_entry, new_dl); |
| 173 | goto the_end; | 175 | goto the_end; |
| @@ -179,24 +181,35 @@ kqueue_compare_dir_list | |||
| 179 | new_entry = XCAR (dl1); | 181 | new_entry = XCAR (dl1); |
| 180 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), | 182 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), |
| 181 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { | 183 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { |
| 182 | pending_events = Fcons (new_entry, pending_events); | 184 | pending_dl = Fcons (new_entry, pending_dl); |
| 183 | new_dl = Fdelq (new_entry, new_dl); | 185 | new_dl = Fdelq (new_entry, new_dl); |
| 184 | goto the_end; | 186 | goto the_end; |
| 185 | } | 187 | } |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 188 | new_entry = assq_no_quit (XCAR (old_entry), pending_events); | 190 | /* Check, whether this a pending file. */ |
| 189 | if (NILP (new_entry)) | 191 | new_entry = assq_no_quit (XCAR (old_entry), pending_dl); |
| 192 | |||
| 193 | if (NILP (new_entry)) { | ||
| 194 | /* Check, whether this is an already deleted file (by rename). */ | ||
| 195 | for (dl1 = deleted_dl; ! NILP (dl1); dl1 = XCDR (dl1)) { | ||
| 196 | new_entry = XCAR (dl1); | ||
| 197 | if (strcmp (SSDATA (XCAR (XCDR (old_entry))), | ||
| 198 | SSDATA (XCAR (XCDR (new_entry)))) == 0) { | ||
| 199 | deleted_dl = Fdelq (new_entry, deleted_dl); | ||
| 200 | goto the_end; | ||
| 201 | } | ||
| 202 | } | ||
| 190 | /* The file has been deleted. */ | 203 | /* The file has been deleted. */ |
| 191 | kqueue_generate_event | 204 | kqueue_generate_event |
| 192 | (watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil); | 205 | (watch_object, Fcons (Qdelete, Qnil), XCAR (XCDR (old_entry)), Qnil); |
| 193 | else { | 206 | |
| 207 | } else { | ||
| 194 | /* The file has been renamed. */ | 208 | /* The file has been renamed. */ |
| 195 | kqueue_generate_event | 209 | kqueue_generate_event |
| 196 | (watch_object, Fcons (Qrename, Qnil), | 210 | (watch_object, Fcons (Qrename, Qnil), |
| 197 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); | 211 | XCAR (XCDR (old_entry)), XCAR (XCDR (new_entry))); |
| 198 | new_dl = Fdelq (new_entry, new_dl); | 212 | pending_dl = Fdelq (new_entry, pending_dl); |
| 199 | pending_events = Fdelq (new_entry, pending_events); | ||
| 200 | } | 213 | } |
| 201 | 214 | ||
| 202 | the_end: | 215 | the_end: |
| @@ -226,8 +239,8 @@ kqueue_compare_dir_list | |||
| 226 | new_dl = Fdelq (entry, new_dl); | 239 | new_dl = Fdelq (entry, new_dl); |
| 227 | } | 240 | } |
| 228 | 241 | ||
| 229 | /* Parse through the resulting pending_events_list. */ | 242 | /* Parse through the resulting pending_dl list. */ |
| 230 | dl = pending_events; | 243 | dl = pending_dl; |
| 231 | while (1) { | 244 | while (1) { |
| 232 | Lisp_Object entry; | 245 | Lisp_Object entry; |
| 233 | if (NILP (dl)) | 246 | if (NILP (dl)) |
| @@ -239,18 +252,21 @@ kqueue_compare_dir_list | |||
| 239 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil); | 252 | (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (entry)), Qnil); |
| 240 | 253 | ||
| 241 | dl = XCDR (dl); | 254 | dl = XCDR (dl); |
| 242 | pending_events = Fdelq (entry, pending_events); | 255 | pending_dl = Fdelq (entry, pending_dl); |
| 243 | } | 256 | } |
| 244 | 257 | ||
| 245 | /* At this point, old_dl, new_dl and pending_events shall be empty. | 258 | /* At this point, old_dl, new_dl and pending_dl shall be empty. |
| 246 | Let's make a check for this (might be removed once the code is | 259 | deleted_dl might not be empty when there was a rename to a |
| 247 | stable). */ | 260 | nonexisting file. Let's make a check for this (might be removed |
| 261 | once the code is stable). */ | ||
| 248 | if (! NILP (old_dl)) | 262 | if (! NILP (old_dl)) |
| 249 | report_file_error ("Old list not empty", old_dl); | 263 | report_file_error ("Old list not empty", old_dl); |
| 250 | if (! NILP (new_dl)) | 264 | if (! NILP (new_dl)) |
| 251 | report_file_error ("New list not empty", new_dl); | 265 | report_file_error ("New list not empty", new_dl); |
| 252 | if (! NILP (pending_events)) | 266 | if (! NILP (pending_dl)) |
| 253 | report_file_error ("Pending events not empty", new_dl); | 267 | report_file_error ("Pending events list not empty", pending_dl); |
| 268 | // if (! NILP (deleted_dl)) | ||
| 269 | // report_file_error ("Deleted events list not empty", deleted_dl); | ||
| 254 | 270 | ||
| 255 | /* Replace old directory listing with the new one. */ | 271 | /* Replace old directory listing with the new one. */ |
| 256 | XSETCDR (Fnthcdr (make_number (3), watch_object), | 272 | XSETCDR (Fnthcdr (make_number (3), watch_object), |