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

atagar at torproject.org atagar at torproject.org
Sat May 31 19:08:36 UTC 2014


commit fcf49ad8afe52a36553fabbeaa3741566fa299f6
Author: Damian Johnson <atagar at 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'] == '':



More information about the tor-commits mailing list