summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Albinus <michael.albinus@gmx.de>2016-03-04 14:01:36 +0000
committerMichael Albinus <michael.albinus@gmx.de>2016-03-04 14:01:36 +0000
commit484967796755051c4045cdcc26b0d3d129cc72ad (patch)
treec2fc0747c640beb5f6056494728e775bf9c20883
parentca4e30058eba0531f38fff75f14734acffab84ea (diff)
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 <sys/resource.h>. (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.
-rw-r--r--etc/NEWS3
-rw-r--r--etc/PROBLEMS11
-rw-r--r--lisp/autorevert.el6
-rw-r--r--src/kqueue.c24
-rw-r--r--test/lisp/filenotify-tests.el86
5 files changed, 91 insertions, 39 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 172577601a..d7e1b83989 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 d531367711..7d780371d4 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 <http://debbugs.gnu.org/22814>.
-
-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 bde8eb84a6..14e39bddd2 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 <http://debbugs.gnu.org/22814>.
- (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 a69d06da3a..7e3bfdd574 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -29,6 +29,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "process.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#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 9f0c0ed0dc..d3610f0008 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")