Changeset 1758
- Timestamp:
- 10/18/07 21:43:38
- Files:
-
- trunk/cherrypy/_cpconfig.py (modified) (1 diff)
- trunk/cherrypy/restsrv/wspbus.py (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cpconfig.py
r1752 r1758 302 302 elif k == 'deadlock_poll_freq': 303 303 cherrypy.timeout_monitor.frequency = v 304 elif k == 'reexec_retry':305 engine.publish('restart', 'retry', v)306 304 elif k == 'SIGHUP': 307 305 engine.listeners['SIGHUP'] = set([v]) trunk/cherrypy/restsrv/wspbus.py
r1757 r1758 36 36 The Bus object in this package uses topic-based publish-subscribe 37 37 messaging to accomplish all this. A few topic channels are built in 38 ('start', 'stop', 'exit', 'restart' and 'graceful'). Frameworks and39 site containers are free to define their own. If a message is sent to a 40 channel that hasnot been defined or has no listeners, there is no effect.38 ('start', 'stop', 'exit', and 'graceful'). Frameworks and site containers 39 are free to define their own. If a message is sent to a channel that has 40 not been defined or has no listeners, there is no effect. 41 41 42 42 In general, there should only ever be a single Bus object per process. … … 48 48 those methods then publish to subscribed listeners on the channel for 49 49 the new state. 50 51 O 52 | 53 V 54 STOPPING --> STOPPED --> X 55 A A | 56 | \___ | 57 | \ | 58 | V V 59 STARTED <-- STARTING 60 50 61 """ 51 62 63 import os 52 64 try: 53 65 set … … 58 70 import time 59 71 import traceback as _traceback 60 import os 61 import exceptions 72 62 73 63 74 # Use a flag to indicate the state of the bus. … … 77 88 states = states 78 89 state = states.STOPPED 90 execv = False 79 91 80 92 def __init__(self): … … 83 95 self.listeners = dict( 84 96 [(channel, set()) for channel 85 in ('start', 'stop', 'exit', ' restart', 'graceful')])97 in ('start', 'stop', 'exit', 'graceful')]) 86 98 self._priorities = {} 87 99 … … 142 154 """Stop all services and exit the process.""" 143 155 self.stop() 144 145 156 self.log('Bus exit') 146 157 self.publish('exit') … … 148 159 149 160 def restart(self): 150 """Restart the process (may close connections).""" 151 if self.execv: 152 raise exceptions.AssertionError("Already restarting.") 153 161 """Restart the process (may close connections). 162 163 This method does not restart the process from the calling thread; 164 instead, it stops the bus and asks the main thread to call execv. 165 """ 154 166 self.execv = True 155 167 self.stop() 156 157 self.log('Bus restart')158 self.publish('restart')159 168 160 169 def graceful(self): … … 182 191 def _do_execv(self): 183 192 """Re-execute the current process.""" 184 # Waiting for the child threads to finish is necessary on OS X. 193 self.execv = False 194 195 self.log('Bus restart') 196 self.publish('exit') 197 198 # Re-execute the current process. We must do this in the 199 # main thread (which is the only thread that should be 200 # calling block) because OS X doesn't allow execv to be 201 # called in a child thread very well. 202 # Waiting for ALL child threads to finish is necessary on OS X. 185 203 # 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 204 self.log("Waiting for child threads to terminate...") 205 for t in threading.enumerate(): 206 if t != threading.currentThread(): 207 t.join() 208 191 209 args = sys.argv[:] 192 210 self.log('Re-spawning %s' % ' '.join(args)) 193 211 args.insert(0, sys.executable) 194 212 195 213 if sys.platform == 'win32': 196 214 args = ['"%s"' % arg for arg in args] 197 215 198 216 os.execv(sys.executable, args) 199 200 217 201 218 def stop(self): 202 219 """Stop all services."""

