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