Ticket #637: signals_in_engine.patch
-
_cpconfig.py
old new 106 106 'request.show_tracebacks': False, 107 107 'log.screen': False, 108 108 }, 109 "embedded": { 110 # For use with CherryPy embedded in another deployment stack. 111 'engine.autoreload_on': False, 112 'checker.on': False, 113 'tools.log_headers.on': False, 114 'request.show_tracebacks': False, 115 'log.screen': False, 116 'engine.SIGHUP': None, 117 'engine.SIGTERM': None, 118 }, 109 119 "test_suite": { 110 120 'engine.autoreload_on': False, 111 121 'checker.on': False, -
_cpengine.py
old new 16 16 STARTING = None 17 17 STARTED = 1 18 18 19 try:20 if hasattr(signal, "SIGHUP"):21 def SIGHUP(signum=None, frame=None):22 cherrypy.engine.reexec()23 signal.signal(signal.SIGHUP, SIGHUP)24 19 25 if hasattr(signal, "SIGTERM"):26 def SIGTERM(signum=None, frame=None):27 cherrypy.server.stop()28 cherrypy.engine.stop()29 signal.signal(signal.SIGTERM, SIGTERM)30 except ValueError, _signal_exc:31 if _signal_exc.args[0] != "signal only works in main thread":32 raise33 34 35 20 class PerpetualTimer(threading._Timer): 36 21 37 22 def run(self): … … 43 28 44 29 45 30 class Engine(object): 46 """Application interface for (HTTP) servers, plus process controls.""" 31 """Interface for (HTTP) applications, plus process controls. 47 32 33 Servers and gateways should not instantiate Request objects directly. 34 Instead, they should ask an Engine object for a request via the 35 Engine.request method. 36 37 Blocking is completely optional! The Engine's blocking, signal and 38 interrupt handling, privilege dropping, and autoreload features are 39 not a good idea when driving CherryPy applications from another 40 deployment tool (but an Engine is a great deployment tool itself). 41 By calling start(blocking=False), you avoid blocking and interrupt- 42 handling issues. By setting Engine.SIGHUP and Engine.SIGTERM to None, 43 you can completely disable the signal handling (and therefore disable 44 autoreloads triggered by SIGHUP). Set Engine.autoreload_on to False 45 to disable autoreload entirely. 46 """ 47 48 48 # Configurable attributes 49 49 request_class = _cprequest.Request 50 50 response_class = _cprequest.Response … … 81 81 82 82 self.state = STARTED 83 83 84 self._set_signals() 85 84 86 freq = self.deadlock_poll_freq 85 87 if freq > 0: 86 88 self.monitor_thread = PerpetualTimer(freq, self.monitor) … … 263 265 264 266 self.start() 265 267 268 269 # Signal handling # 270 271 SIGHUP = None 272 SIGTERM = None 273 274 if hasattr(signal, "SIGHUP"): 275 def SIGHUP(self, signum=None, frame=None): 276 self.reexec() 277 278 if hasattr(signal, "SIGTERM"): 279 def SIGTERM(signum=None, frame=None): 280 cherrypy.server.stop() 281 self.stop() 282 283 def _set_signals(self): 284 if self.SIGHUP: 285 signal.signal(signal.SIGHUP, self.SIGHUP) 286 if self.SIGTERM: 287 signal.signal(signal.SIGTERM, self.SIGTERM) 288 289 290 # Drop privileges # 291 266 292 # Special thanks to Gavin Baker: http://antonym.org/node/100. 267 293 try: 268 294 import pwd, grp

