Changeset 1757
- Timestamp:
- 10/18/07 21:18:33
- Files:
-
- trunk/cherrypy/__init__.py (modified) (1 diff)
- trunk/cherrypy/restsrv/plugins.py (modified) (2 diffs)
- trunk/cherrypy/restsrv/win32.py (modified) (1 diff)
- trunk/cherrypy/restsrv/wspbus.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1756 r1757 213 213 engine.autoreload = restsrv.plugins.Autoreloader(engine) 214 214 engine.autoreload.subscribe() 215 restsrv.plugins.Reexec(engine).subscribe()216 215 restsrv.plugins.ThreadManager(engine).subscribe() 217 216 trunk/cherrypy/restsrv/plugins.py
r1755 r1757 95 95 """Python signal handler (self.set_handler subscribes it for you).""" 96 96 self.bus.publish(self.signals[signum]) 97 98 99 class Reexec(SimplePlugin):100 """A process restarter (using execv) for the 'restart' WSPBus channel.101 102 retry: the number of seconds to wait for all parent threads to stop.103 This is only necessary for platforms like OS X which error if all104 threads are not absolutely terminated before calling execv.105 """106 107 def __init__(self, bus, retry=2):108 self.bus = bus109 self.retry = retry110 111 def restart(self):112 """Re-execute the current process."""113 args = sys.argv[:]114 self.bus.log('Re-spawning %s' % ' '.join(args))115 args.insert(0, sys.executable)116 117 if sys.platform == 'win32':118 args = ['"%s"' % arg for arg in args]119 120 # Some platforms (OS X) will error if all threads are not121 # ABSOLUTELY terminated, and there doesn't seem to be a way122 # around it other than waiting for the threads to stop.123 # See http://www.cherrypy.org/ticket/581.124 for trial in xrange(self.retry * 10):125 try:126 os.execv(sys.executable, args)127 return128 except OSError, x:129 if x.errno != 45:130 raise131 time.sleep(0.1)132 else:133 raise134 97 135 98 … … 390 353 if mtime is None or mtime > oldtime: 391 354 # The file has been deleted or modified. 355 self.bus.log("Restarting because %s changed." % filename) 356 self.thread.cancel() 392 357 self.bus.restart() 358 return 393 359 394 360 trunk/cherrypy/restsrv/win32.py
r1740 r1757 73 73 try: 74 74 win32event.WaitForSingleObject(event, win32event.INFINITE) 75 if self.execv: 76 self._do_execv() 75 77 except SystemExit: 76 78 self.log('SystemExit raised: shutting down bus') trunk/cherrypy/restsrv/wspbus.py
r1752 r1757 58 58 import time 59 59 import traceback as _traceback 60 60 import os 61 import exceptions 61 62 62 63 # Use a flag to indicate the state of the bus. … … 78 79 79 80 def __init__(self): 81 self.execv = False 80 82 self.state = states.STOPPED 81 83 self.listeners = dict( … … 147 149 def restart(self): 148 150 """Restart the process (may close connections).""" 151 if self.execv: 152 raise exceptions.AssertionError("Already restarting.") 153 154 self.execv = True 149 155 self.stop() 150 156 … … 162 168 while self.state != state: 163 169 time.sleep(interval) 170 if self.execv: 171 self._do_execv() 164 172 except (KeyboardInterrupt, IOError): 165 173 # The time.sleep call might raise … … 172 180 raise 173 181 182 def _do_execv(self): 183 """Re-execute the current process.""" 184 # Waiting for the child threads to finish is necessary on OS X. 185 # See: http://www.cherrypy.org/ticket/581 186 self.log("Waiting for child threads...") 187 threads = [t for t in threading.enumerate() if t != threading.currentThread()] 188 for t in threads: 189 t.join() 190 191 args = sys.argv[:] 192 self.log('Re-spawning %s' % ' '.join(args)) 193 args.insert(0, sys.executable) 194 195 if sys.platform == 'win32': 196 args = ['"%s"' % arg for arg in args] 197 198 os.execv(sys.executable, args) 199 200 174 201 def stop(self): 175 202 """Stop all services."""

