Commit db111f71 authored by maruel@chromium.org's avatar maruel@chromium.org

Add automatic auto-flushing stdout.

An automated work around for python lack of stdout flushing.
This design simplifies life once parallel checkout is enabled.

TEST=none
BUG=none

Review URL: http://codereview.chromium.org/3342024

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@58819 0039d316-1c4b-4281-b951-d872f2087c98
parent 6985efce
...@@ -1197,8 +1197,8 @@ def Main(argv): ...@@ -1197,8 +1197,8 @@ def Main(argv):
options.entries_filename = options.config_filename + '_entries' options.entries_filename = options.config_filename + '_entries'
if options.jobs < 1: if options.jobs < 1:
parser.error('--jobs must be 1 or higher') parser.error('--jobs must be 1 or higher')
# Useful for --jobs. # Always autoflush so buildbot doesn't kill us during lengthy operations.
options.stdout = sys.stdout options.stdout = gclient_utils.StdoutAutoFlush(sys.stdout)
# These hacks need to die. # These hacks need to die.
if not hasattr(options, 'revisions'): if not hasattr(options, 'revisions'):
......
...@@ -285,6 +285,30 @@ def CheckCallAndFilterAndHeader(args, always=False, **kwargs): ...@@ -285,6 +285,30 @@ def CheckCallAndFilterAndHeader(args, always=False, **kwargs):
return CheckCallAndFilter(args, **kwargs) return CheckCallAndFilter(args, **kwargs)
class StdoutAutoFlush(object):
"""Automatically flush after N seconds."""
def __init__(self, stdout, delay=10):
self.lock = threading.Lock()
self.stdout = stdout
self.delay = delay
self.last_flushed_at = time.time()
self.stdout.flush()
def write(self, out):
"""Thread-safe."""
self.stdout.write(out)
should_flush = False
with self.lock:
if (time.time() - self.last_flushed_at) > self.delay:
should_flush = True
self.last_flushed_at = time.time()
if should_flush:
self.stdout.flush()
def flush(self):
self.stdout.flush()
def CheckCallAndFilter(args, stdout=None, filter_fn=None, def CheckCallAndFilter(args, stdout=None, filter_fn=None,
print_stdout=None, call_filter_on_first_line=False, print_stdout=None, call_filter_on_first_line=False,
**kwargs): **kwargs):
...@@ -308,7 +332,6 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None, ...@@ -308,7 +332,6 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None,
**kwargs) **kwargs)
# Do a flush of stdout before we begin reading from the subprocess's stdout # Do a flush of stdout before we begin reading from the subprocess's stdout
last_flushed_at = time.time()
stdout.flush() stdout.flush()
# Also, we need to forward stdout to prevent weird re-ordering of output. # Also, we need to forward stdout to prevent weird re-ordering of output.
...@@ -329,12 +352,6 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None, ...@@ -329,12 +352,6 @@ def CheckCallAndFilter(args, stdout=None, filter_fn=None,
else: else:
filter_fn(in_line) filter_fn(in_line)
in_line = '' in_line = ''
# Flush at least 10 seconds between line writes. We wait at least 10
# seconds to avoid overloading the reader that called us with output,
# which can slow busy readers down.
if (time.time() - last_flushed_at) > 10:
last_flushed_at = time.time()
stdout.flush()
in_byte = kid.stdout.read(1) in_byte = kid.stdout.read(1)
# Flush the rest of buffered output. This is only an issue with # Flush the rest of buffered output. This is only an issue with
# stdout/stderr not ending with a \n. # stdout/stderr not ending with a \n.
......
...@@ -28,7 +28,7 @@ class GclientUtilsUnittest(GclientUtilBase): ...@@ -28,7 +28,7 @@ class GclientUtilsUnittest(GclientUtilBase):
'GetGClientRootAndEntries', 'GetNamedNodeText', 'GetGClientRootAndEntries', 'GetNamedNodeText',
'GetNodeNamedAttributeText', 'PathDifference', 'ParseXML', 'Popen', 'GetNodeNamedAttributeText', 'PathDifference', 'ParseXML', 'Popen',
'PrintableObject', 'RemoveDirectory', 'SplitUrlRevision', 'PrintableObject', 'RemoveDirectory', 'SplitUrlRevision',
'SyntaxErrorToError', 'WorkItem', 'StdoutAutoFlush', 'SyntaxErrorToError', 'WorkItem',
'errno', 'logging', 'os', 're', 'stat', 'subprocess', 'sys', 'errno', 'logging', 'os', 're', 'stat', 'subprocess', 'sys',
'threading', 'time', 'xml', 'threading', 'time', 'xml',
] ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment