1 /* Filesystem notifications support for GNU Emacs on the Microsoft Windows API.
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 /* Written by Eli Zaretskii <eliz@gnu.org>.
23 For each watch request, we launch a separate worker thread. The
24 worker thread runs the watch_worker function, which issues an
25 asynchronous call to ReadDirectoryChangesW, and then waits in
26 SleepEx for that call to complete. Waiting in SleepEx puts the
27 thread in an "alertable" state, so it wakes up when either (a) the
28 call to ReadDirectoryChangesW completes, or (b) the main thread
29 instructs the worker thread to terminate by sending it an APC, see
32 When the ReadDirectoryChangesW call completes, its completion
33 routine watch_completion is automatically called. watch_completion
34 stashes the received file events in a buffer used to communicate
35 them to the main thread (using a critical section, so that several
36 threads could use the same buffer), posts a special message,
37 WM_EMACS_FILENOTIFY, to the Emacs's message queue, and returns.
38 That causes the SleepEx function call inside watch_worker to
39 return, and watch_worker then issues another call to
40 ReadDirectoryChangesW. (Except when it does not, see below.)
42 In a GUI session, The WM_EMACS_FILENOTIFY message, posted to the
43 message queue gets dispatched to the main Emacs window procedure,
44 which queues it for processing by w32_read_socket. When
45 w32_read_socket sees this message, it accesses the buffer with file
46 notifications (using a critical section), extracts the information,
47 converts it to a series of FILE_NOTIFY_EVENT events, and stuffs
48 them into the input event queue to be processed by keyboard.c input
49 machinery (read_char via a call to kbd_buffer_get_event).
51 In a non-GUI session, we send the WM_EMACS_FILENOTIFY message to
52 the main (a.k.a. "Lisp") thread instead, since there are no window
53 procedures in console programs. That message wakes up
54 MsgWaitForMultipleObjects inside sys_select, which then signals to
55 its caller that some keyboard input is available. This causes
56 w32_console_read_socket to be called, which accesses the buffer
57 with file notifications and stuffs them into the input event queue
58 for keyboard.c to process.
60 When the FILE_NOTIFY_EVENT event is processed by keyboard.c's
61 kbd_buffer_get_event, it is converted to a Lispy event that can be
62 bound to a command. The default binding is w32notify-handle-event,
65 After w32_read_socket or w32_console_read_socket are done
66 processing the notifications, they reset a flag signaling to all
67 watch worker threads that the notifications buffer is available for
70 When the watch is removed by a call to w32notify-rm-watch, the main
71 thread requests that the worker thread terminates by queuing an APC
72 for the worker thread. The APC specifies the watch_end function to
73 be called. watch_end calls CancelIo on the outstanding
74 ReadDirectoryChangesW call and closes the handle on which the
75 watched directory was open. When watch_end returns, the
76 watch_completion function is called one last time with the
77 ERROR_OPERATION_ABORTED status, which causes it to clean up and set
78 a flag telling watch_worker to exit without issuing another
79 ReadDirectoryChangesW call. Since watch_worker is the thread
80 procedure of the worker thread, exiting it causes the thread to
81 exit. The main thread waits for some time for the worker thread to
82 exit, and if it doesn't, terminates it forcibly. */
87 /* must include CRT headers *before* config.h */
93 #include "w32term.h" /* for enter_crit/leave_crit and WM_EMACS_FILENOTIFY */
94 #include "w32common.h" /* for OS version data */
95 #include "w32.h" /* for w32_strerror */
98 #include "frame.h" /* needed by termhooks.h */
99 #include "termhooks.h" /* for FILE_NOTIFY_EVENT */
101 #define DIRWATCH_SIGNATURE 0x01233210
103 struct notification
{
104 BYTE
*buf
; /* buffer for ReadDirectoryChangesW */
105 OVERLAPPED
*io_info
; /* the OVERLAPPED structure for async I/O */
106 BOOL subtree
; /* whether to watch subdirectories */
107 DWORD filter
; /* bit mask for events to watch */
108 char *watchee
; /* the file we are interested in */
109 HANDLE dir
; /* handle to the watched directory */
110 HANDLE thr
; /* handle to the thread that watches */
111 volatile int terminate
; /* if non-zero, request for the thread to terminate */
115 /* Used for communicating notifications to the main thread. */
116 volatile int notification_buffer_in_use
;
117 BYTE file_notifications
[16384];
118 DWORD notifications_size
;
119 void *notifications_desc
;
121 static Lisp_Object Qfile_name
, Qdirectory_name
, Qattributes
, Qsize
;
122 static Lisp_Object Qlast_write_time
, Qlast_access_time
, Qcreation_time
;
123 static Lisp_Object Qsecurity_desc
, Qsubtree
, watch_list
;
125 /* Signal to the main thread that we have file notifications for it to
128 send_notifications (BYTE
*info
, DWORD info_size
, void *desc
,
129 volatile int *terminate
)
132 FRAME_PTR f
= SELECTED_FRAME ();
134 /* A single buffer is used to communicate all notifications to the
135 main thread. Since both the main thread and several watcher
136 threads could be active at the same time, we use a critical area
137 and an "in-use" flag to synchronize them. A watcher thread can
138 only put its notifications in the buffer if it acquires the
139 critical area and finds the "in-use" flag reset. The main thread
140 resets the flag after it is done processing notifications.
142 FIXME: is there a better way of dealing with this? */
143 while (!done
&& !*terminate
)
146 if (!notification_buffer_in_use
)
149 memcpy (file_notifications
, info
, info_size
);
150 notifications_size
= info_size
;
151 notifications_desc
= desc
;
152 /* If PostMessage fails, the message queue is full. If that
153 happens, the last thing they will worry about is file
154 notifications. So we effectively discard the
155 notification in that case. */
156 if ((FRAME_TERMCAP_P (f
)
157 /* We send the message to the main (a.k.a. "Lisp")
158 thread, where it will wake up MsgWaitForMultipleObjects
159 inside sys_select, causing it to report that there's
160 some keyboard input available. This will in turn cause
161 w32_console_read_socket to be called, which will pick
162 up the file notifications. */
163 && PostThreadMessage (dwMainThreadId
, WM_EMACS_FILENOTIFY
, 0, 0))
165 && PostMessage (FRAME_W32_WINDOW (f
),
166 WM_EMACS_FILENOTIFY
, 0, 0)))
167 notification_buffer_in_use
= 1;
176 /* An APC routine to cancel outstanding directory watch. Invoked by
177 the main thread via QueueUserAPC. This is needed because only the
178 thread that issued the ReadDirectoryChangesW call can call CancelIo
179 to cancel that. (CancelIoEx is only available since Vista, so we
180 cannot use it on XP.) */
182 watch_end (ULONG_PTR arg
)
184 HANDLE hdir
= (HANDLE
)arg
;
186 if (hdir
&& hdir
!= INVALID_HANDLE_VALUE
)
193 /* A completion routine (a.k.a. "APC function") for handling events
194 read by ReadDirectoryChangesW. Called by the OS when the thread
195 which issued the asynchronous ReadDirectoryChangesW call is in the
196 "alertable state", i.e. waiting inside SleepEx call. */
198 watch_completion (DWORD status
, DWORD bytes_ret
, OVERLAPPED
*io_info
)
200 struct notification
*dirwatch
;
202 /* Who knows what happened? Perhaps the OVERLAPPED structure was
203 freed by someone already? In any case, we cannot do anything
204 with this request, so just punt and skip it. FIXME: should we
205 raise the 'terminate' flag in this case? */
209 /* We have a pointer to our dirwatch structure conveniently stashed
210 away in the hEvent member of the OVERLAPPED struct. According to
211 MSDN documentation of ReadDirectoryChangesW: "The hEvent member
212 of the OVERLAPPED structure is not used by the system, so you can
214 dirwatch
= (struct notification
*)io_info
->hEvent
;
215 if (status
== ERROR_OPERATION_ABORTED
)
217 /* We've been called because the main thread told us to issue
218 CancelIo on the directory we watch, and watch_end did so.
219 The directory handle is already closed. We should clean up
220 and exit, signaling to the thread worker routine not to
221 issue another call to ReadDirectoryChangesW. Note that we
222 don't free the dirwatch object itself nor the memory consumed
223 by its buffers; this is done by the main thread in
224 remove_watch. Calling malloc/free from a thread other than
225 the main thread is a no-no. */
226 dirwatch
->dir
= NULL
;
227 dirwatch
->terminate
= 1;
231 /* Tell the main thread we have notifications for it. */
232 send_notifications (dirwatch
->buf
, bytes_ret
, dirwatch
,
233 &dirwatch
->terminate
);
237 /* Worker routine for the watch thread. */
239 watch_worker (LPVOID arg
)
241 struct notification
*dirwatch
= (struct notification
*)arg
;
250 status
= ReadDirectoryChangesW (dirwatch
->dir
, dirwatch
->buf
, 16384,
251 dirwatch
->subtree
, dirwatch
->filter
,
253 dirwatch
->io_info
, watch_completion
);
256 DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ()));
257 /* We cannot remove the dirwatch object from watch_list,
258 because we are in a separate thread. For the same
259 reason, we also cannot free memory consumed by the
260 buffers allocated for the dirwatch object. So we close
261 the directory handle, but do not free the object itself
262 or its buffers. We also don't touch the signature.
263 This way, remove_watch can still identify the object,
264 remove it, and free its memory. */
265 CloseHandle (dirwatch
->dir
);
266 dirwatch
->dir
= NULL
;
270 /* Sleep indefinitely until awoken by the I/O completion, which
271 could be either a change notification or a cancellation of the
273 sleep_result
= SleepEx (INFINITE
, TRUE
);
274 } while (!dirwatch
->terminate
);
279 /* Launch a thread to watch changes to FILE in a directory open on
281 static struct notification
*
282 start_watching (const char *file
, HANDLE hdir
, BOOL subdirs
, DWORD flags
)
284 struct notification
*dirwatch
= xzalloc (sizeof (struct notification
));
287 dirwatch
->signature
= DIRWATCH_SIGNATURE
;
288 dirwatch
->buf
= xmalloc (16384);
289 dirwatch
->io_info
= xzalloc (sizeof(OVERLAPPED
));
290 /* Stash a pointer to dirwatch structure for use by the completion
291 routine. According to MSDN documentation of ReadDirectoryChangesW:
292 "The hEvent member of the OVERLAPPED structure is not used by the
293 system, so you can use it yourself." */
294 dirwatch
->io_info
->hEvent
= dirwatch
;
295 dirwatch
->subtree
= subdirs
;
296 dirwatch
->filter
= flags
;
297 dirwatch
->watchee
= xstrdup (file
);
298 dirwatch
->terminate
= 0;
299 dirwatch
->dir
= hdir
;
301 /* See w32proc.c where it calls CreateThread for the story behind
302 the 2nd and 5th argument in the call to CreateThread. */
303 dirwatch
->thr
= CreateThread (NULL
, 64 * 1024, watch_worker
, (void *)dirwatch
,
308 xfree (dirwatch
->buf
);
309 xfree (dirwatch
->io_info
);
310 xfree (dirwatch
->watchee
);
317 /* Called from the main thread to start watching FILE in PARENT_DIR,
318 subject to FLAGS. If SUBDIRS is TRUE, watch the subdirectories of
319 PARENT_DIR as well. Value is a pointer to 'struct notification'
320 used by the thread that watches the changes. */
321 static struct notification
*
322 add_watch (const char *parent_dir
, const char *file
, BOOL subdirs
, DWORD flags
)
325 struct notification
*dirwatch
= NULL
;
330 hdir
= CreateFile (parent_dir
,
332 /* FILE_SHARE_DELETE doesn't preclude other
333 processes from deleting files inside
335 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
337 FILE_FLAG_BACKUP_SEMANTICS
| FILE_FLAG_OVERLAPPED
,
339 if (hdir
== INVALID_HANDLE_VALUE
)
342 if ((dirwatch
= start_watching (file
, hdir
, subdirs
, flags
)) == NULL
)
348 /* Stop watching a directory specified by a pointer to its dirwatch object. */
350 remove_watch (struct notification
*dirwatch
)
352 if (dirwatch
&& dirwatch
->signature
== DIRWATCH_SIGNATURE
)
356 DWORD exit_code
, err
;
358 /* Only the thread that issued the outstanding I/O call can call
359 CancelIo on it. (CancelIoEx is available only since Vista.)
360 So we need to queue an APC for the worker thread telling it
362 if (!QueueUserAPC (watch_end
, dirwatch
->thr
, (ULONG_PTR
)dirwatch
->dir
))
363 DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ()));
364 /* We also set the terminate flag, for when the thread is
365 waiting on the critical section that never gets acquired.
366 FIXME: is there a cleaner method? Using SleepEx there is a
367 no-no, as that will lead to recursive APC invocations and
369 dirwatch
->terminate
= 1;
370 /* Wait for the thread to exit. FIXME: is there a better method
371 that is not overly complex? */
372 for (i
= 0; i
< 50; i
++)
374 if (!((status
= GetExitCodeThread (dirwatch
->thr
, &exit_code
))
375 && exit_code
== STILL_ACTIVE
))
379 if ((status
== FALSE
&& (err
= GetLastError ()) == ERROR_INVALID_HANDLE
)
380 || exit_code
== STILL_ACTIVE
)
382 if (!(status
== FALSE
&& err
== ERROR_INVALID_HANDLE
))
384 TerminateThread (dirwatch
->thr
, 0);
386 CloseHandle (dirwatch
->dir
);
393 CloseHandle (dirwatch
->thr
);
394 dirwatch
->thr
= NULL
;
396 xfree (dirwatch
->buf
);
397 xfree (dirwatch
->io_info
);
398 xfree (dirwatch
->watchee
);
405 DebPrint (("Unknown dirwatch object!\n"));
411 filter_list_to_flags (Lisp_Object filter_list
)
415 if (NILP (filter_list
))
418 if (!NILP (Fmember (Qfile_name
, filter_list
)))
419 flags
|= FILE_NOTIFY_CHANGE_FILE_NAME
;
420 if (!NILP (Fmember (Qdirectory_name
, filter_list
)))
421 flags
|= FILE_NOTIFY_CHANGE_DIR_NAME
;
422 if (!NILP (Fmember (Qattributes
, filter_list
)))
423 flags
|= FILE_NOTIFY_CHANGE_ATTRIBUTES
;
424 if (!NILP (Fmember (Qsize
, filter_list
)))
425 flags
|= FILE_NOTIFY_CHANGE_SIZE
;
426 if (!NILP (Fmember (Qlast_write_time
, filter_list
)))
427 flags
|= FILE_NOTIFY_CHANGE_LAST_WRITE
;
428 if (!NILP (Fmember (Qlast_access_time
, filter_list
)))
429 flags
|= FILE_NOTIFY_CHANGE_LAST_ACCESS
;
430 if (!NILP (Fmember (Qcreation_time
, filter_list
)))
431 flags
|= FILE_NOTIFY_CHANGE_CREATION
;
432 if (!NILP (Fmember (Qsecurity_desc
, filter_list
)))
433 flags
|= FILE_NOTIFY_CHANGE_SECURITY
;
438 DEFUN ("w32notify-add-watch", Fw32notify_add_watch
,
439 Sw32notify_add_watch
, 3, 3, 0,
440 doc
: /* Add a watch for filesystem events pertaining to FILE.
442 This arranges for filesystem events pertaining to FILE to be reported
443 to Emacs. Use `w32notify-rm-watch' to cancel the watch.
445 Value is a descriptor for the added watch. If the file cannot be
446 watched for some reason, this function signals a `file-error' error.
448 FILTER is a list of conditions for reporting an event. It can include
449 the following symbols:
451 'file-name' -- report file creation, deletion, or renaming
452 'directory-name' -- report directory creation, deletion, or renaming
453 'attributes' -- report changes in attributes
454 'size' -- report changes in file-size
455 'last-write-time' -- report changes in last-write time
456 'last-access-time' -- report changes in last-access time
457 'creation-time' -- report changes in creation time
458 'security-desc' -- report changes in security descriptor
460 If FILE is a directory, and FILTER includes 'subtree', then all the
461 subdirectories will also be watched and changes in them reported.
463 When any event happens that satisfies the conditions specified by
464 FILTER, Emacs will call the CALLBACK function passing it a single
465 argument EVENT, which is of the form
467 (DESCRIPTOR ACTION FILE)
469 DESCRIPTOR is the same object as the one returned by this function.
470 ACTION is the description of the event. It could be any one of the
473 'added' -- FILE was added
474 'removed' -- FILE was deleted
475 'modified' -- FILE's contents or its attributes were modified
476 'renamed-from' -- a file was renamed whose old name was FILE
477 'renamed-to' -- a file was renamed and its new name is FILE
479 FILE is the name of the file whose event is being reported.
481 Note that some networked filesystems, such as Samba-mounted Unix
482 volumes, might not send notifications about file changes. In these
483 cases, this function will return a valid descriptor, but notifications
484 will never come in. Volumes shared from remote Windows machines do
485 generate notifications correctly, though. */)
486 (Lisp_Object file
, Lisp_Object filter
, Lisp_Object callback
)
488 Lisp_Object encoded_file
, watch_object
, watch_descriptor
;
489 char parent_dir
[MAX_PATH
], *basename
;
492 BOOL subdirs
= FALSE
;
493 struct notification
*dirwatch
= NULL
;
494 Lisp_Object lisp_errstr
;
499 /* The underlying features are available only since XP. */
500 if (os_subtype
== OS_9X
501 || (w32_major_version
== 5 && w32_major_version
< 1))
504 report_file_error ("Watching filesystem events is not supported",
508 /* We need a full absolute file name of FILE, and we need to remove
509 any trailing slashes from it, so that GetFullPathName below gets
510 the basename part correctly. */
511 file
= Fdirectory_file_name (Fexpand_file_name (file
, Qnil
));
512 encoded_file
= ENCODE_FILE (file
);
514 fn_len
= GetFullPathName (SDATA (encoded_file
), MAX_PATH
, parent_dir
,
518 errstr
= w32_strerror (0);
520 if (!NILP (Vlocale_coding_system
))
522 = code_convert_string_norecord (build_unibyte_string (errstr
),
523 Vlocale_coding_system
, 0);
525 lisp_errstr
= build_string (errstr
);
526 report_file_error ("GetFullPathName failed",
527 Fcons (lisp_errstr
, Fcons (file
, Qnil
)));
529 /* We need the parent directory without the slash that follows it.
530 If BASENAME is NULL, the argument was the root directory on its
537 if (!NILP (Fmember (Qsubtree
, filter
)))
540 flags
= filter_list_to_flags (filter
);
542 dirwatch
= add_watch (parent_dir
, basename
, subdirs
, flags
);
545 DWORD err
= GetLastError ();
550 errstr
= w32_strerror (err
);
551 if (!NILP (Vlocale_coding_system
))
553 = code_convert_string_norecord (build_unibyte_string (errstr
),
554 Vlocale_coding_system
, 0);
556 lisp_errstr
= build_string (errstr
);
557 report_file_error ("Cannot watch file",
558 Fcons (lisp_errstr
, Fcons (file
, Qnil
)));
561 report_file_error ("Cannot watch file", Fcons (file
, Qnil
));
563 /* Store watch object in watch list. */
564 watch_descriptor
= XIL ((EMACS_INT
)dirwatch
);
565 watch_object
= Fcons (watch_descriptor
, callback
);
566 watch_list
= Fcons (watch_object
, watch_list
);
568 return watch_descriptor
;
571 DEFUN ("w32notify-rm-watch", Fw32notify_rm_watch
,
572 Sw32notify_rm_watch
, 1, 1, 0,
573 doc
: /* Remove an existing watch specified by its WATCH-DESCRIPTOR.
575 WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */)
576 (Lisp_Object watch_descriptor
)
578 Lisp_Object watch_object
;
579 struct notification
*dirwatch
;
582 /* Remove the watch object from watch list. Do this before freeing
583 the object, do that even if we fail to free it, watch_list is
584 kept free of junk. */
585 watch_object
= Fassoc (watch_descriptor
, watch_list
);
586 if (!NILP (watch_object
))
588 watch_list
= Fdelete (watch_object
, watch_list
);
589 dirwatch
= (struct notification
*)XLI (watch_descriptor
);
590 if (w32_valid_pointer_p (dirwatch
, sizeof(struct notification
)))
591 status
= remove_watch (dirwatch
);
595 report_file_error ("Invalid watch descriptor", Fcons (watch_descriptor
,
602 w32_get_watch_object (void *desc
)
604 Lisp_Object descriptor
= XIL ((EMACS_INT
)desc
);
606 /* This is called from the input queue handling code, inside a
607 critical section, so we cannot possibly QUIT if watch_list is not
608 in the right condition. */
609 return NILP (watch_list
) ? Qnil
: assoc_no_quit (descriptor
, watch_list
);
613 globals_of_w32notify (void)
619 syms_of_w32notify (void)
621 DEFSYM (Qfile_name
, "file-name");
622 DEFSYM (Qdirectory_name
, "directory-name");
623 DEFSYM (Qattributes
, "attributes");
624 DEFSYM (Qsize
, "size");
625 DEFSYM (Qlast_write_time
, "last-write-time");
626 DEFSYM (Qlast_access_time
, "last-access-time");
627 DEFSYM (Qcreation_time
, "creation-time");
628 DEFSYM (Qsecurity_desc
, "security-desc");
629 DEFSYM (Qsubtree
, "subtree");
631 defsubr (&Sw32notify_add_watch
);
632 defsubr (&Sw32notify_rm_watch
);
634 staticpro (&watch_list
);
636 Fprovide (intern_c_string ("w32notify"), Qnil
);