Go to the documentation of this file.00001 
00002 
00003 
00004 from __future__ import absolute_import, division, with_statement
00005 import logging
00006 import os
00007 import signal
00008 import sys
00009 from tornado.httpclient import HTTPClient, HTTPError
00010 from tornado.httpserver import HTTPServer
00011 from tornado.ioloop import IOLoop
00012 from tornado.netutil import bind_sockets
00013 from tornado.process import fork_processes, task_id
00014 from tornado.simple_httpclient import SimpleAsyncHTTPClient
00015 from tornado.testing import LogTrapTestCase, get_unused_port
00016 from tornado.web import RequestHandler, Application
00017 
00018 
00019 
00020 
00021 
00022 
00023 class ProcessTest(LogTrapTestCase):
00024     def get_app(self):
00025         class ProcessHandler(RequestHandler):
00026             def get(self):
00027                 if self.get_argument("exit", None):
00028                     
00029                     
00030                     os._exit(int(self.get_argument("exit")))
00031                 if self.get_argument("signal", None):
00032                     os.kill(os.getpid(),
00033                             int(self.get_argument("signal")))
00034                 self.write(str(os.getpid()))
00035         return Application([("/", ProcessHandler)])
00036 
00037     def tearDown(self):
00038         if task_id() is not None:
00039             
00040             
00041             
00042             
00043             
00044             
00045             logging.error("aborting child process from tearDown")
00046             logging.shutdown()
00047             os._exit(1)
00048         
00049         signal.alarm(0)
00050         super(ProcessTest, self).tearDown()
00051 
00052     def test_multi_process(self):
00053         self.assertFalse(IOLoop.initialized())
00054         port = get_unused_port()
00055 
00056         def get_url(path):
00057             return "http://127.0.0.1:%d%s" % (port, path)
00058         sockets = bind_sockets(port, "127.0.0.1")
00059         
00060         signal.alarm(5)
00061         try:
00062             id = fork_processes(3, max_restarts=3)
00063         except SystemExit, e:
00064             
00065             
00066             self.assertEqual(e.code, 0)
00067             self.assertTrue(task_id() is None)
00068             for sock in sockets:
00069                 sock.close()
00070             return
00071         try:
00072             if id in (0, 1):
00073                 self.assertEqual(id, task_id())
00074                 server = HTTPServer(self.get_app())
00075                 server.add_sockets(sockets)
00076                 IOLoop.instance().start()
00077             elif id == 2:
00078                 self.assertEqual(id, task_id())
00079                 for sock in sockets:
00080                     sock.close()
00081                 
00082                 
00083                 
00084                 
00085                 client = HTTPClient(SimpleAsyncHTTPClient)
00086 
00087                 def fetch(url, fail_ok=False):
00088                     try:
00089                         return client.fetch(get_url(url))
00090                     except HTTPError, e:
00091                         if not (fail_ok and e.code == 599):
00092                             raise
00093 
00094                 
00095                 fetch("/?exit=2", fail_ok=True)
00096                 fetch("/?exit=3", fail_ok=True)
00097 
00098                 
00099                 int(fetch("/").body)
00100 
00101                 
00102                 
00103                 
00104                 
00105                 
00106                 
00107                 
00108 
00109                 
00110                 fetch("/?exit=0", fail_ok=True)
00111                 
00112                 pid = int(fetch("/").body)
00113                 fetch("/?exit=4", fail_ok=True)
00114                 pid2 = int(fetch("/").body)
00115                 self.assertNotEqual(pid, pid2)
00116 
00117                 
00118                 fetch("/?exit=0", fail_ok=True)
00119 
00120                 os._exit(0)
00121         except Exception:
00122             logging.error("exception in child process %d", id, exc_info=True)
00123             raise
00124 
00125 
00126 if os.name != 'posix' or sys.platform == 'cygwin':
00127     
00128     del ProcessTest