From: Ben Darnell Date: Fri, 27 Mar 2015 03:36:43 +0000 (-0400) Subject: Add Subprocess.wait_for_exit, a coro-friendly set_exit_callback(). X-Git-Tag: v4.2.0b1~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24677828d2ce10b3f85ec9c18d38d54c1ab0c382;p=thirdparty%2Ftornado.git Add Subprocess.wait_for_exit, a coro-friendly set_exit_callback(). Fixes #1391. --- diff --git a/tornado/process.py b/tornado/process.py index 3790ca0a5..fb9254fc0 100644 --- a/tornado/process.py +++ b/tornado/process.py @@ -29,6 +29,7 @@ import time from binascii import hexlify +from tornado.concurrent import Future from tornado import ioloop from tornado.iostream import PipeIOStream from tornado.log import gen_log @@ -258,6 +259,22 @@ class Subprocess(object): Subprocess._waiting[self.pid] = self Subprocess._try_cleanup_process(self.pid) + def wait_for_exit(self): + """Returns a `.Future` which resolves when the process exits. + + Usage:: + + ret = yield proc.wait_for_exit() + + This is a coroutine-friendly alternative to `set_exit_callback` + (and a replacement for the blocking `subprocess.Popen.wait`). + + .. versionadded:: 4.2 + """ + future = Future() + self.set_exit_callback(future.set_result) + return future + @classmethod def initialize(cls, io_loop=None): """Initializes the ``SIGCHLD`` handler. diff --git a/tornado/test/process_test.py b/tornado/test/process_test.py index de727607a..6abfabd28 100644 --- a/tornado/test/process_test.py +++ b/tornado/test/process_test.py @@ -13,7 +13,7 @@ from tornado.ioloop import IOLoop from tornado.log import gen_log from tornado.process import fork_processes, task_id, Subprocess from tornado.simple_httpclient import SimpleAsyncHTTPClient -from tornado.testing import bind_unused_port, ExpectLog, AsyncTestCase +from tornado.testing import bind_unused_port, ExpectLog, AsyncTestCase, gen_test from tornado.test.util import unittest, skipIfNonUnix from tornado.web import RequestHandler, Application @@ -200,6 +200,16 @@ class SubprocessTest(AsyncTestCase): self.assertEqual(ret, 0) self.assertEqual(subproc.returncode, ret) + @gen_test + def test_sigchild_future(self): + skip_if_twisted() + Subprocess.initialize() + self.addCleanup(Subprocess.uninitialize) + subproc = Subprocess([sys.executable, '-c', 'pass']) + ret = yield subproc.wait_for_exit() + self.assertEqual(ret, 0) + self.assertEqual(subproc.returncode, ret) + def test_sigchild_signal(self): skip_if_twisted() Subprocess.initialize(io_loop=self.io_loop)