From: Michael Albinus Date: Fri, 4 Mar 2016 14:01:36 +0000 (+0000) Subject: Fix Bug#22814 X-Git-Tag: emacs-26.0.90~2374 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=484967796755051c4045cdcc26b0d3d129cc72ad;p=emacs.git Fix Bug#22814 * lisp/autorevert.el (global-auto-revert-mode): Do not set `auto-revert-use-notify' to nil. * etc/NEWS: Mention this. * etc/PROBLEMS: Remove problem Bug#22814. * src/kqueue.c: Include . (Fkqueue_add_watch): Limit the number of used file descriptors. (Bug#22814) * test/lisp/filenotify-tests.el (file-notify--test-remote-enabled) (file-notify-test00-availability, file-notify-test01-add-watch) (file-notify-test02-events, file-notify-test06-many-events): Use #' read syntax for functions. (file-notify-test05-dir-validity) (file-notify-test06-many-events): Simplify directory creation. (file-notify-test09-sufficient-ressources): New test. --- diff --git a/etc/NEWS b/etc/NEWS index 172577601af..d7e1b839895 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -114,6 +114,9 @@ different group ID. +++ *** New connection method "doas" for OpenBSD hosts. +--- +** `auto-revert-use-notify' is set back to t in `global-auto-revert-mode'. + * New Modes and Packages in Emacs 25.2 diff --git a/etc/PROBLEMS b/etc/PROBLEMS index d5313677113..7d780371d46 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -600,17 +600,6 @@ you have a personal configuration file (normally ~/.aspell.conf), it can cause this error. Remove that file, execute 'ispell-kill-ispell' in Emacs, and then try spell-checking again. -*** Emacs eats all file descriptors when using kqueue file notifications. -See . - -When you have a large number of buffers running auto-revert-mode, and -Emacs is configured to use the kqueue file notification library, it -uses an own file descriptor for every watched file. On systems with a -small limit of file descriptors allowed per process, like OS X, you -could run out of file descriptors. You won't be able to open new files. - -auto-revert-use-notify is set to nil in global-auto-revert-mode, therefore. - * Runtime problems related to font handling ** Characters are displayed as empty boxes or with wrong font under X. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index bde8eb84a64..14e39bddd2e 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -458,11 +458,7 @@ specifies in the mode line." :global t :group 'auto-revert :lighter global-auto-revert-mode-text (auto-revert-set-timer) (if global-auto-revert-mode - (progn - ;; We disable file notification because it could use too many - ;; ressources. See . - (setq auto-revert-use-notify nil) - (auto-revert-buffers)) + (auto-revert-buffers) (dolist (buf (buffer-list)) (with-current-buffer buf (when auto-revert-use-notify diff --git a/src/kqueue.c b/src/kqueue.c index a69d06da3ae..7e3bfdd5746 100644 --- a/src/kqueue.c +++ b/src/kqueue.c @@ -29,6 +29,10 @@ along with GNU Emacs. If not, see . */ #include "keyboard.h" #include "process.h" +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif /* HAVE_SYS_RESOURCE_H */ + /* File handle for kqueue. */ static int kqueuefd = -1; @@ -368,9 +372,12 @@ only when the upper directory of the renamed file is watched. */) (Lisp_Object file, Lisp_Object flags, Lisp_Object callback) { Lisp_Object watch_object, dir_list; - int fd, oflags; + int maxfd, fd, oflags; u_short fflags = 0; struct kevent kev; +#ifdef HAVE_GETRLIMIT + struct rlimit rlim; +#endif /* HAVE_GETRLIMIT */ /* Check parameters. */ CHECK_STRING (file); @@ -383,6 +390,21 @@ only when the upper directory of the renamed file is watched. */) if (! FUNCTIONP (callback)) wrong_type_argument (Qinvalid_function, callback); + /* Check available file descriptors. */ +#ifdef HAVE_GETRLIMIT + if (! getrlimit (RLIMIT_NOFILE, &rlim)) + maxfd = rlim.rlim_cur; + else +#endif /* HAVE_GETRLIMIT */ + maxfd = 256; + + /* We assume 50 file descriptors are sufficient for the rest of Emacs. */ + if ((maxfd - 50) < XINT (Flength (watch_list))) + xsignal2 + (Qfile_notify_error, + build_string ("File watching not possible, no file descriptor left"), + Flength (watch_list)); + if (kqueuefd < 0) { /* Create kqueue descriptor. */ diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 9f0c0ed0dc1..d3610f00080 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -140,7 +140,7 @@ being the result.") (setq desc (file-notify-add-watch file-notify-test-remote-temporary-file-directory - '(change) 'ignore)))) + '(change) #'ignore)))) (setq file-notify--test-remote-enabled-checked (cons t desc)) (when desc (file-notify-rm-watch desc)))) ;; Return result. @@ -180,7 +180,7 @@ remote host, or nil." (message "Library: `%s'" (file-notify--test-library)) (should (setq file-notify--test-desc - (file-notify-add-watch temporary-file-directory '(change) 'ignore))) + (file-notify-add-watch temporary-file-directory '(change) #'ignore))) ;; Cleanup. (file-notify--test-cleanup)) @@ -199,23 +199,23 @@ remote host, or nil." ;; Check, that different valid parameters are accepted. (should (setq file-notify--test-desc - (file-notify-add-watch temporary-file-directory '(change) 'ignore))) + (file-notify-add-watch temporary-file-directory '(change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) (should (setq file-notify--test-desc (file-notify-add-watch - temporary-file-directory '(attribute-change) 'ignore))) + temporary-file-directory '(attribute-change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) (should (setq file-notify--test-desc (file-notify-add-watch - temporary-file-directory '(change attribute-change) 'ignore))) + temporary-file-directory '(change attribute-change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) (write-region "any text" nil file-notify--test-tmpfile nil 'no-message) (should (setq file-notify--test-desc (file-notify-add-watch - file-notify--test-tmpfile '(change attribute-change) 'ignore))) + file-notify--test-tmpfile '(change attribute-change) #'ignore))) (file-notify-rm-watch file-notify--test-desc) (delete-file file-notify--test-tmpfile) @@ -238,7 +238,7 @@ remote host, or nil." (should (equal (should-error (file-notify-add-watch - file-notify--test-tmpfile1 '(change attribute-change) 'ignore)) + file-notify--test-tmpfile1 '(change attribute-change) #'ignore)) `(file-notify-error "Directory does not exist" ,file-notify--test-tmpfile))) @@ -361,7 +361,7 @@ longer than timeout seconds for the events to be delivered." (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; cygwin recognizes only `deleted' and `stopped' events. @@ -381,7 +381,7 @@ longer than timeout seconds for the events to be delivered." (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; cygwin recognizes only `deleted' and `stopped' events. @@ -414,7 +414,7 @@ longer than timeout seconds for the events to be delivered." file-notify--test-desc (file-notify-add-watch temporary-file-directory - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; w32notify does not raise `deleted' and `stopped' @@ -445,7 +445,7 @@ longer than timeout seconds for the events to be delivered." file-notify--test-desc (file-notify-add-watch temporary-file-directory - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; w32notify does not distinguish between `changed' and @@ -487,7 +487,7 @@ longer than timeout seconds for the events to be delivered." file-notify--test-desc (file-notify-add-watch temporary-file-directory - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; w32notify does not raise `deleted' and `stopped' @@ -521,7 +521,7 @@ longer than timeout seconds for the events to be delivered." (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile - '(attribute-change) 'file-notify--test-event-handler))) + '(attribute-change) #'file-notify--test-event-handler))) (file-notify--test-with-events (cond ;; w32notify does not distinguish between `changed' and @@ -743,9 +743,9 @@ longer than timeout seconds for the events to be delivered." (unwind-protect (progn - (setq file-notify--test-tmpfile - (file-name-as-directory (file-notify--test-make-temp-name))) - (make-directory file-notify--test-tmpfile) + (should + (setq file-notify--test-tmpfile + (make-temp-file "file-notify-test-parent" t))) (should (setq file-notify--test-desc (file-notify-add-watch @@ -765,9 +765,9 @@ longer than timeout seconds for the events to be delivered." (unwind-protect (progn - (setq file-notify--test-tmpfile - (file-name-as-directory (file-notify--test-make-temp-name))) - (make-directory file-notify--test-tmpfile) + (should + (setq file-notify--test-tmpfile + (make-temp-file "file-notify-test-parent" t))) (should (setq file-notify--test-desc (file-notify-add-watch @@ -795,13 +795,14 @@ longer than timeout seconds for the events to be delivered." ;; Under cygwin events arrive in random order. Impossible to define a test. (skip-unless (not (eq system-type 'cygwin))) - (setq file-notify--test-tmpfile (file-notify--test-make-temp-name)) - (make-directory file-notify--test-tmpfile) + (should + (setq file-notify--test-tmpfile + (make-temp-file "file-notify-test-parent" t))) (should (setq file-notify--test-desc (file-notify-add-watch file-notify--test-tmpfile - '(change) 'file-notify--test-event-handler))) + '(change) #'file-notify--test-event-handler))) (unwind-protect (let ((n 1000) source-file-list target-file-list @@ -1058,6 +1059,47 @@ the file watch." (file-notify--deftest-remote file-notify-test08-watched-file-in-watched-dir "Check `file-notify-test08-watched-file-in-watched-dir' for remote files.") +(ert-deftest file-notify-test09-sufficient-ressources () + "Check that file notification does not use too many ressources." + :tags '(:expensive-test) + (skip-unless (file-notify--test-local-enabled)) + ;; This test is intended for kqueue only. + (skip-unless (string-equal (file-notify--test-library) "kqueue")) + + (should + (setq file-notify--test-tmpfile + (make-temp-file "file-notify-test-parent" t))) + (unwind-protect + (let ((temporary-file-directory file-notify--test-tmpfile) + descs) + (should-error + (while t + ;; We watch directories, because we want to reach the upper + ;; limit. Watching a file might not be sufficient, because + ;; most of the libraries implement this as watching the + ;; upper directory. + (setq file-notify--test-tmpfile1 + (make-temp-file "file-notify-test-parent" t) + descs + (cons + (should + (file-notify-add-watch + file-notify--test-tmpfile1 '(change) #'ignore)) + descs))) + :type 'file-notify-error) + ;; Remove watches. If we don't do it prior removing + ;; directories, Emacs crashes in batch mode. + (dolist (desc descs) + (file-notify-rm-watch desc)) + ;; Remove directories. + (delete-directory file-notify--test-tmpfile 'recursive)) + + ;; Cleanup. + (file-notify--test-cleanup))) + +(file-notify--deftest-remote file-notify-test09-sufficient-ressources + "Check `file-notify-test09-sufficient-ressources' for remote files.") + (defun file-notify-test-all (&optional interactive) "Run all tests for \\[file-notify]." (interactive "p")