Permalink
Browse files

Add instant autoreload on platforms supporting kqueue.

  • Loading branch information...
1 parent 8faaf03 commit 8f09ec61f8d24fcd4ad4a4438be4d90300d55175 @aaugustin aaugustin committed Oct 30, 2013
Showing with 45 additions and 0 deletions.
  1. +45 −0 django/utils/autoreload.py
View
@@ -65,6 +65,16 @@
except ImportError:
pass
+try:
+ import select
+ select.kevent, select.kqueue
+ USE_KQUEUE = True
+
+ import resource
+ NOFILES_SOFT, NOFILES_HARD = resource.getrlimit(resource.RLIMIT_NOFILE)
+except AttributeError:
+ USE_KQUEUE = False
+
RUN_RELOADER = True
_mtimes = {}
@@ -119,6 +129,39 @@ def update_watch(sender=None, **kwargs):
# If we are here the code must have changed.
return True
+def kqueue_code_changed():
+ """
+ Checks for changed code using kqueue. After being called
+ it blocks until a change event has been fired.
+ """
+ # Maximum number of open file descriptors is typically too low (256).
+ filenames = list(gen_filenames())
+ resource.setrlimit(resource.RLIMIT_NOFILE,
+ (NOFILES_SOFT + len(filenames), NOFILES_HARD))
+
+ kqueue = select.kqueue()
+ fds = [open(filename) for filename in filenames]
+
+ _filter = select.KQ_FILTER_VNODE
+ flags = select.KQ_EV_ADD
+ fflags = (
+ select.KQ_NOTE_DELETE |
+ select.KQ_NOTE_WRITE |
+ select.KQ_NOTE_EXTEND |
+ select.KQ_NOTE_ATTRIB |
+ select.KQ_NOTE_LINK |
+ select.KQ_NOTE_RENAME |
+ select.KQ_NOTE_REVOKE
+ )
+ kevents = [select.kevent(fd, _filter, flags, fflags) for fd in fds]
+ kqueue.control(kevents, 1)
+
+ for fd in fds:
+ fd.close()
+ kqueue.close()
+
+ return True
+
def code_changed():
global _mtimes, _win
for filename in gen_filenames():
@@ -178,6 +221,8 @@ def reloader_thread():
ensure_echo_on()
if USE_INOTIFY:
fn = inotify_code_changed
+ elif USE_KQUEUE:
+ fn = kqueue_code_changed
else:
fn = code_changed
while RUN_RELOADER:

0 comments on commit 8f09ec6

Please sign in to comment.