# % sort time
# % stats 20
-from tornado.ioloop import IOLoop
from tornado.options import define, options, parse_command_line
from tornado.web import RequestHandler, Application
+import asyncio
import random
-import signal
-import subprocess
-
-try:
- xrange
-except NameError:
- xrange = range
# choose a random port to avoid colliding with TIME_WAIT sockets left over
# from previous runs.
# --n=15000 for its JIT to reach full effectiveness
define("num_runs", type=int, default=1)
-define("ioloop", type=str, default=None)
-
class RootHandler(RequestHandler):
def get(self):
pass
-def handle_sigchld(sig, frame):
- IOLoop.current().add_callback_from_signal(IOLoop.current().stop)
-
-
def main():
parse_command_line()
- if options.ioloop:
- IOLoop.configure(options.ioloop)
- for i in xrange(options.num_runs):
- run()
+ for i in range(options.num_runs):
+ asyncio.run(run())
-def run():
- io_loop = IOLoop(make_current=True)
+async def run():
app = Application([("/", RootHandler)])
port = random.randrange(options.min_port, options.max_port)
- app.listen(port, address='127.0.0.1')
- signal.signal(signal.SIGCHLD, handle_sigchld)
+ app.listen(port, address="127.0.0.1")
args = ["ab"]
args.extend(["-n", str(options.n)])
args.extend(["-c", str(options.c)])
# just stops the progress messages printed to stderr
args.append("-q")
args.append("http://127.0.0.1:%d/" % port)
- subprocess.Popen(args)
- io_loop.start()
- io_loop.close()
- io_loop.clear_current()
+ proc = await asyncio.create_subprocess_exec(*args)
+ await proc.wait()
-if __name__ == '__main__':
+if __name__ == "__main__":
main()
other interaction with the `IOLoop` must be done from that
`IOLoop`'s thread. `add_callback()` may be used to transfer
control from other threads to the `IOLoop`'s thread.
-
- To add a callback from a signal handler, see
- `add_callback_from_signal`.
"""
raise NotImplementedError()
) -> None:
"""Calls the given callback on the next I/O loop iteration.
- Safe for use from a Python signal handler; should not be used
- otherwise.
+ Intended to be afe for use from a Python signal handler; should not be
+ used otherwise.
+
+ .. deprecated:: 6.4
+ Use ``asyncio.AbstractEventLoop.add_signal_handler`` instead.
+ This method is suspected to have been broken since Tornado 5.0 and
+ will be removed in version 7.0.
"""
raise NotImplementedError()
def add_callback_from_signal(
self, callback: Callable, *args: Any, **kwargs: Any
) -> None:
+ warnings.warn("add_callback_from_signal is deprecated", DeprecationWarning)
try:
self.asyncio_loop.call_soon_threadsafe(
self._run_callback, functools.partial(callback, *args, **kwargs)
the server into multiple processes and managing subprocesses.
"""
+import asyncio
import os
import multiprocessing
import signal
_initialized = False
_waiting = {} # type: ignore
- _old_sigchld = None
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.io_loop = ioloop.IOLoop.current()
"""
if cls._initialized:
return
- io_loop = ioloop.IOLoop.current()
- cls._old_sigchld = signal.signal(
- signal.SIGCHLD,
- lambda sig, frame: io_loop.add_callback_from_signal(cls._cleanup),
- )
+ loop = asyncio.get_event_loop()
+ loop.add_signal_handler(signal.SIGCHLD, cls._cleanup)
cls._initialized = True
@classmethod
"""Removes the ``SIGCHLD`` handler."""
if not cls._initialized:
return
- signal.signal(signal.SIGCHLD, cls._old_sigchld)
+ loop = asyncio.get_event_loop()
+ loop.remove_signal_handler(signal.SIGCHLD)
cls._initialized = False
@classmethod
return
assert ret_pid == pid
subproc = cls._waiting.pop(pid)
- subproc.io_loop.add_callback_from_signal(subproc._set_returncode, status)
+ subproc.io_loop.add_callback(subproc._set_returncode, status)
def _set_returncode(self, status: int) -> None:
if sys.platform == "win32":
def test_add_callback_from_signal(self):
# cheat a little bit and just run this normally, since we can't
# easily simulate the races that happen with real signal handlers
- self.io_loop.add_callback_from_signal(self.stop)
+ with ignore_deprecation():
+ self.io_loop.add_callback_from_signal(self.stop)
self.wait()
def test_add_callback_from_signal_other_thread(self):
other_ioloop = IOLoop()
thread = threading.Thread(target=other_ioloop.start)
thread.start()
- other_ioloop.add_callback_from_signal(other_ioloop.stop)
+ with ignore_deprecation():
+ other_ioloop.add_callback_from_signal(other_ioloop.stop)
thread.join()
other_ioloop.close()