aboutsummaryrefslogtreecommitdiffstats
path: root/src/kqueue.c
diff options
context:
space:
mode:
authorMichael Albinus2015-11-20 18:06:42 +0000
committerMichael Albinus2015-11-25 15:07:12 +0100
commit0247489fed0f70b2abf960de48bc4432381a581b (patch)
tree28e4de085d082377dfee71b800fff0b644cea3e1 /src/kqueue.c
parent5154781141c2305c24103beb358453d30a838921 (diff)
downloademacs-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.c48
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
111kqueue_compare_dir_list 111kqueue_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),