[stem/master] Close stdout/stderr after the tor process initializes

commit fcf49ad8afe52a36553fabbeaa3741566fa299f6 Author: Damian Johnson <atagar@torproject.org> Date: Thu May 29 08:48:51 2014 -0700 Close stdout/stderr after the tor process initializes We use tor's stdout and stderr to determine two things... * at what stage it has bootstrapped to * errors if tor fails to start After startup, however, we stop listing to stdout which can cause Tor to lock up if it's registering a lot of NOTICE level messages... https://trac.torproject.org/projects/tor/ticket/9862 Tested by the following script. Before this fix tor hung after ~3 seconds. With it things happily chug along... import time import stem.process from stem.control import EventType, Controller tor_process = stem.process.launch_tor_with_config( config = { 'ControlPort': '9051', 'Log': 'DEBUG stdout', }, take_ownership = True, ) with Controller.from_port() as controller: controller.authenticate() def heartbeat(event): print "%s - %s / %s" % (time.time(), event.read, event.written) controller.add_event_listener(heartbeat, EventType.BW) print "Press any key to quit..." raw_input() --- docs/change_log.rst | 7 ++++--- stem/process.py | 3 +++ test/integ/process.py | 2 +- test/runner.py | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/change_log.rst b/docs/change_log.rst index 6b71913..279f2bb 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -52,9 +52,10 @@ The following are only available within Stem's `git repository * Added `support for TB_EMPTY events <api/response.html#stem.response.events.TokenBucketEmptyEvent>`_ (:spec:`6f2919a`) * Added `support for HS_DESC events <api/response.html#stem.response.events.HSDescEvent>`_ (:spec:`a67ac4d`, :trac:`10807`) * Changed :func:`~stem.control.Controller.get_network_status` and :func:`~stem.control.Controller.get_network_statuses` to provide :class:`~stem.descriptor.router_status_entry.RouterStatusEntryMicroV3` if Tor is using microdescriptors (:trac:`7646`) - * The :func:`~stem.connection.connect_port` and :func:`~stem.connection.connect_socket_file` didn't properly mark the Controller it returned as being authenticated, causing event listening among other things to fail. - * The :func:`~stem.control.Controller.add_event_listener` method couldn't accept event types that Stem didn't already recognize. - * The :class:`~stem.exit_policy.ExitPolicy` class couldn't be pickled. + * The :func:`~stem.connection.connect_port` and :func:`~stem.connection.connect_socket_file` didn't properly mark the Controller it returned as being authenticated, causing event listening among other things to fail + * The :func:`~stem.control.Controller.add_event_listener` method couldn't accept event types that Stem didn't already recognize + * The :class:`~stem.exit_policy.ExitPolicy` class couldn't be pickled + * Tor instances spawned with :func:`~stem.process.launch_tor` and :func:`~stem.process.launch_tor_with_config` could hang due to unread stdout content, we now close stdout and stderr once tor finishes bootstrapping (:trac:`9862`) * **Descriptors** diff --git a/stem/process.py b/stem/process.py index ad05659..c9fe863 100644 --- a/stem/process.py +++ b/stem/process.py @@ -159,6 +159,9 @@ def launch_tor(tor_cmd = 'tor', args = None, torrc_path = None, completion_perce if timeout: signal.alarm(0) # stop alarm + tor_process.stdout.close() + tor_process.stderr.close() + if temp_file: try: os.remove(temp_file) diff --git a/test/integ/process.py b/test/integ/process.py index d87dda4..b06e500 100644 --- a/test/integ/process.py +++ b/test/integ/process.py @@ -65,7 +65,7 @@ class TestProcess(unittest.TestCase): control_socket.close() tor_process.kill() - tor_process.communicate() + tor_process.wait() def test_launch_tor_with_timeout(self): """ diff --git a/test/runner.py b/test/runner.py index 3ad78f2..07cbd34 100644 --- a/test/runner.py +++ b/test/runner.py @@ -349,7 +349,7 @@ class Runner(object): except OSError: pass - self._tor_process.communicate() # blocks until the process is done + self._tor_process.wait() # blocks until the process is done # if we've made a temporary data directory then clean it up if self._test_dir and CONFIG['integ.test_directory'] == '':
participants (1)
-
atagar@torproject.org