Changeset 1995
- Timestamp:
- 06/29/08 01:12:27
- Files:
-
- trunk/cherrypy/cherryd (modified) (5 diffs)
- trunk/cherrypy/test/test_states.py (modified) (8 diffs)
- trunk/cherrypy/test/test_states_demo.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/cherryd
r1989 r1995 1 1 #! /usr/bin/env python 2 2 """The CherryPy daemon.""" 3 4 import sys 3 5 4 6 import cherrypy … … 7 9 8 10 def start(configfiles=None, daemonize=False, environment=None, 9 fastcgi=False, pidfile=None ):11 fastcgi=False, pidfile=None, imports=None): 10 12 """Subscribe all engine plugins and start the engine.""" 13 for i in imports: 14 exec "import %s" % i 15 11 16 for c in configfiles or []: 12 17 cherrypy.config.update(c) … … 45 50 46 51 # Always start the engine; this will start all other services 47 engine.start() 48 engine.block() 52 try: 53 engine.start() 54 except: 55 # Assume the error has been logged already via bus.log. 56 sys.exit(1) 57 else: 58 engine.block() 49 59 50 60 … … 61 71 p.add_option('-f', action="store_true", dest='fastcgi', 62 72 help="start a fastcgi server instead of the default HTTP server") 73 p.add_option('-i', '--import', action="append", dest='imports', 74 help="specify modules to import") 63 75 p.add_option('-p', '--pidfile', dest='pidfile', default=None, 64 76 help="store the process id in the given file") … … 66 78 67 79 start(options.config, options.daemonize, 68 options.environment, options.fastcgi, options.pidfile) 80 options.environment, options.fastcgi, options.pidfile, 81 options.imports) 69 82 trunk/cherrypy/test/test_states.py
r1989 r1995 14 14 thisdir = os.path.join(os.getcwd(), os.path.dirname(__file__)) 15 15 PID_file_path = os.path.join(thisdir, 'pid_for_test_daemonize') 16 17 18 def write_conf(scheme='http', starterror=False): 19 if scheme.lower() == 'https': 20 serverpem = os.path.join(thisdir, 'test.pem') 21 ssl = """ 22 server.ssl_certificate: r'%s' 23 server.ssl_private_key: r'%s' 24 """ % (serverpem, serverpem) 25 else: 26 ssl = "" 27 28 if starterror: 29 starterror = "starterror: True" 30 else: 31 starterror = "" 32 33 conffile = open(os.path.join(thisdir, 'test_states.conf'), 'wb') 34 conffile.write("""[global] 35 server.socket_host: '%(host)s' 36 server.socket_port: %(port)s 37 log.screen: False 38 log.error_file: r'%(error_log)s' 39 log.access_file: r'%(access_log)s' 40 %(ssl)s 41 %(starterror)s 42 """ % {'host': host, 43 'port': port, 44 'error_log': os.path.join(thisdir, 'test_states_demo.error.log'), 45 'access_log': os.path.join(thisdir, 'test_states_demo.access.log'), 46 'ssl': ssl, 47 'starterror': starterror, 48 }) 49 conffile.close() 50 51 52 def spawn_cp(configfile=os.path.join(thisdir, 'test_states.conf'), 53 wait=False, daemonize=False): 54 """Start cherryd in a subprocess.""" 55 host = cherrypy.server.socket_host 56 port = cherrypy.server.socket_port 57 cherrypy._cpserver.wait_for_free_port(host, port) 58 59 args = [sys.executable, os.path.join(thisdir, '..', 'cherryd'), 60 '-c', configfile, '-i', 'cherrypy.test.test_states_demo'] 61 62 if sys.platform != 'win32': 63 args.append('-p') 64 args.append(PID_file_path) 65 66 # Spawn the process and wait, when this returns, the original process 67 # is finished. If it daemonized properly, we should still be able 68 # to access pages. 69 if daemonize: 70 args.append('-d') 71 72 if wait: 73 result = os.spawnl(os.P_WAIT, sys.executable, *args) 74 else: 75 result = os.spawnl(os.P_NOWAIT, sys.executable, *args) 76 cherrypy._cpserver.wait_for_occupied_port(host, port) 77 78 return result 79 80 def wait(pid): 81 """Wait for the process with the given pid to exit.""" 82 try: 83 try: 84 # Mac, UNIX 85 os.wait() 86 except AttributeError: 87 # Windows 88 os.waitpid(pid, 0) 89 except OSError, x: 90 if x.args != (10, 'No child processes'): 91 raise 16 92 17 93 … … 261 337 262 338 # Start the demo script in a new process 263 demoscript = os.path.join(os.getcwd(), os.path.dirname(__file__), 264 "test_states_demo.py") 265 host = cherrypy.server.socket_host 266 port = cherrypy.server.socket_port 267 cherrypy._cpserver.wait_for_free_port(host, port) 268 269 args = [sys.executable, demoscript, host, str(port)] 270 if self.scheme == "https": 271 args.append('-ssl') 272 pid = os.spawnl(os.P_NOWAIT, sys.executable, *args) 273 cherrypy._cpserver.wait_for_occupied_port(host, port) 274 339 write_conf(scheme=self.scheme) 340 pid = spawn_cp() 275 341 try: 276 342 self.getPage("/start") … … 281 347 282 348 # Touch the file 283 os.utime( demoscript, None)349 os.utime(os.path.join(thisdir, "test_states_demo.py"), None) 284 350 285 351 # Give the autoreloader time to re-exec the process … … 295 361 # Shut down the spawned process 296 362 self.getPage("/exit") 297 298 try: 299 try: 300 # Mac, UNIX 301 print os.wait() 302 except AttributeError: 303 # Windows 304 print os.waitpid(pid, 0) 305 except OSError, x: 306 if x.args != (10, 'No child processes'): 307 raise 363 wait(pid) 308 364 309 365 def test_5_Start_Error(self): … … 312 368 return 313 369 314 # Start the demo script in a new process315 demoscript = os.path.join(os.getcwd(), os.path.dirname(__file__),316 "test_states_demo.py")317 host = cherrypy.server.socket_host318 port = cherrypy.server.socket_port319 320 370 # If a process errors during start, it should stop the engine 321 371 # and exit with a non-zero exit code. 322 args = [sys.executable, demoscript, host, str(port), '-starterror'] 323 if self.scheme == "https": 324 args.append('-ssl') 325 exit_code = os.spawnl(os.P_WAIT, sys.executable, *args) 372 write_conf(scheme=self.scheme, starterror=True) 373 exit_code = spawn_cp(wait=True) 326 374 if exit_code == 0: 327 375 self.fail("Process failed to return nonzero exit code.") … … 330 378 class DaemonizeTests(helper.CPWebCase): 331 379 332 def test_ 1_Daemonize(self):380 def test_daemonize(self): 333 381 if not self.server_class: 334 382 print "skipped (no server) ", … … 339 387 340 388 # Start the demo script in a new process 341 demoscript = os.path.join(os.getcwd(), os.path.dirname(__file__),342 "test_states_demo.py")343 host = cherrypy.server.socket_host344 port = cherrypy.server.socket_port345 cherrypy._cpserver.wait_for_free_port(host, port)346 347 args = [sys.executable, demoscript, host, str(port), '-daemonize']348 if self.scheme == "https":349 args.append('-ssl')350 389 # Spawn the process and wait, when this returns, the original process 351 390 # is finished. If it daemonized properly, we should still be able 352 391 # to access pages. 353 exit_code = os.spawnl(os.P_WAIT, sys.executable, *args)354 cherrypy._cpserver.wait_for_occupied_port(host, port)392 write_conf(scheme=self.scheme) 393 exit_code = spawn_cp(wait=True, daemonize=True) 355 394 356 395 # Give the server some time to start up … … 368 407 # Shut down the spawned process 369 408 self.getPage("/exit") 370 371 try: 372 print os.waitpid(pid, 0) 373 except OSError, x: 374 if x.args != (10, 'No child processes'): 375 raise 409 wait(pid) 376 410 377 411 # Wait until here to test the exit code because we want to ensure 378 412 # that we wait for the daemon to finish running before we fail. 379 413 if exit_code != 0: 380 self.fail("Daemonized p rocess failed to exit cleanly")414 self.fail("Daemonized parent process failed to exit cleanly.") 381 415 382 416 trunk/cherrypy/test/test_states_demo.py
r1926 r1995 5 5 6 6 import cherrypy 7 from cherrypy.process import plugins8 thisdir = os.path.join(os.getcwd(), os.path.dirname(__file__))9 PID_file_path = os.path.join(thisdir, 'pid_for_test_daemonize')10 7 11 8 … … 37 34 exit.exposed = True 38 35 36 def starterror(): 37 if cherrypy.config.get('starterror', False): 38 zerodiv = 1 / 0 39 cherrypy.engine.subscribe('start', starterror, priority=6) 39 40 40 if __name__ == '__main__': 41 conf = {"server.socket_host": sys.argv[1], 42 "server.socket_port": int(sys.argv[2]), 43 "log.screen": False, 44 "log.error_file": os.path.join(thisdir, 'test_states_demo.error.log'), 45 "log.access_file": os.path.join(thisdir, 'test_states_demo.access.log'), 46 } 47 48 if '-ssl' in sys.argv[3:]: 49 localDir = os.path.dirname(__file__) 50 serverpem = os.path.join(os.getcwd(), localDir, 'test.pem') 51 conf['server.ssl_certificate'] = serverpem 52 conf['server.ssl_private_key'] = serverpem 53 54 if '-daemonize' in sys.argv[3:]: 55 # Sometimes an exception happens during exit; 56 # try to make sure we get a non_zero exit code. 57 old_exitfunc = sys.exitfunc 58 def exitfunc(): 59 try: 60 old_exitfunc() 61 except SystemExit: 62 raise 63 except: 64 raise SystemExit(1) 65 sys.exitfunc = exitfunc 66 67 plugins.Daemonizer(cherrypy.engine).subscribe() 68 plugins.PIDFile(cherrypy.engine, PID_file_path).subscribe() 69 70 if '-starterror' in sys.argv[3:]: 71 cherrypy.engine.subscribe('start', lambda: 1/0, priority=6) 72 73 # This is in a special order for a reason: 74 # it allows test_states to wait_for_occupied_port 75 # and then immediately call getPage without getting 503. 76 cherrypy.config.update(conf) 77 cherrypy.tree.mount(Root(), config={'global': conf}) 78 try: 79 cherrypy.engine.start() 80 except ZeroDivisionError: 81 sys.exit(1) 82 cherrypy.engine.block() 41 cherrypy.tree.mount(Root(), '/', {'/': {}})

