]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Add a workaround for a bug in os.execv when used on Mac OS X versions
authorBen Darnell <bdarnell@beaker.local>
Thu, 25 Feb 2010 00:37:11 +0000 (16:37 -0800)
committerBen Darnell <bdarnell@beaker.local>
Thu, 25 Feb 2010 00:37:11 +0000 (16:37 -0800)
prior to 10.6 when there are multiple threads in the process.

tornado/autoreload.py

index 583cdc96f50c1951d689bb1ed4d5c58a42324bad..4b3ab364c520895612045fd49067ef6a84fb275a 100644 (file)
@@ -21,6 +21,7 @@ and Google AppEngine.
 """
 
 import functools
+import errno
 import ioloop
 import logging
 import os
@@ -41,7 +42,13 @@ def start(io_loop=None, check_time=500):
     scheduler.start()
 
 
+_reload_attempted = False
+
 def _reload_on_update(io_loop, modify_times):
+    global _reload_attempted
+    if _reload_attempted:
+        # We already tried to reload and it didn't work, so don't try again.
+        return
     for module in sys.modules.values():
         path = getattr(module, "__file__", None)
         if not path: continue
@@ -56,9 +63,26 @@ def _reload_on_update(io_loop, modify_times):
             continue
         if modify_times[path] != modified:
             logging.info("%s modified; restarting server", path)
+            _reload_attempted = True
             for fd in io_loop._handlers.keys():
                 try:
                     os.close(fd)
                 except:
                     pass
-            os.execv(sys.executable, [sys.executable] + sys.argv)
+            try:
+                os.execv(sys.executable, [sys.executable] + sys.argv)
+            except OSError, e:
+                # Mac OS X versions prior to 10.6 do not support execv in
+                # a process that contains multiple threads.  Instead of
+                # re-executing in the current process, start a new one
+                # and cause the current process to exit.  This isn't
+                # ideal since the new process is detached from the parent
+                # terminal and thus cannot easily be killed with ctrl-C,
+                # but it's better than not being able to autoreload at
+                # all.
+                # Unfortunately the errno returned in this case does not
+                # appear to be consistent, so we can't easily check for
+                # this error specifically.
+                os.spawnv(os.P_NOWAIT, sys.executable,
+                          [sys.executable] + sys.argv)
+                sys.exit(0)