Skip to content

Commit 4397d75

Browse files
committed
Make timeouts also on Windows based on last output timestamp
1 parent 208c2d6 commit 4397d75

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

asv/util.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,25 +359,50 @@ def get_content(header=None):
359359
is_timeout = False
360360

361361
if WIN:
362-
start_time = time.time()
362+
start_time = [time.time()]
363363
was_timeout = [False]
364364

365+
def stdout_reader_run():
366+
while True:
367+
c = proc.stdout.read(1)
368+
if not c:
369+
break
370+
start_time[0] = time.time()
371+
stdout_chunks.append(c)
372+
373+
def stderr_reader_run():
374+
while True:
375+
c = proc.stderr.read(1)
376+
if not c:
377+
break
378+
start_time[0] = time.time()
379+
stderr_chunks.append(c)
380+
365381
def watcher_run():
366382
while proc.returncode is None:
367383
time.sleep(0.1)
368-
if time.time() - start_time > timeout:
384+
if time.time() - start_time[0] > timeout:
369385
was_timeout[0] = True
370386
proc.terminate()
371387

372388
watcher = threading.Thread(target=watcher_run)
373389
watcher.start()
390+
391+
stdout_reader = threading.Thread(target=stdout_reader_run)
392+
stdout_reader.start()
393+
394+
stderr_reader = threading.Thread(target=stderr_reader_run)
395+
stderr_reader.start()
396+
374397
try:
375-
stdout, stderr = proc.communicate()
398+
proc.wait()
376399
finally:
377400
if proc.returncode is None:
378401
proc.terminate()
379402
proc.wait()
380403
watcher.join()
404+
stderr_reader.join()
405+
stdout_reader.join()
381406

382407
is_timeout = was_timeout[0]
383408
else:
@@ -450,8 +475,9 @@ def sig_forward(signum, frame):
450475

451476
stdout_chunks.append(proc.stdout.read())
452477
stderr_chunks.append(proc.stderr.read())
453-
stdout = b''.join(stdout_chunks)
454-
stderr = b''.join(stderr_chunks)
478+
479+
stdout = b''.join(stdout_chunks)
480+
stderr = b''.join(stderr_chunks)
455481

456482
stdout = stdout.decode('utf-8', 'replace')
457483
stderr = stderr.decode('utf-8', 'replace')

test/test_subprocess.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,28 @@ def test_exception():
8686
assert False, "Expected exception"
8787

8888

89+
def test_output_timeout():
90+
# Check that timeout is determined based on last output, not based
91+
# on start time.
92+
code = r"""
93+
import time
94+
import sys
95+
for j in range(3):
96+
time.sleep(0.5)
97+
sys.stdout.write('.')
98+
sys.stdout.flush()
99+
"""
100+
output = util.check_output([sys.executable, "-c", code], timeout=0.75)
101+
assert output == '.'*3
102+
103+
try:
104+
util.check_output([sys.executable, "-c", code], timeout=0.25)
105+
except util.ProcessError as e:
106+
assert e.retcode == util.TIMEOUT_RETCODE
107+
else:
108+
assert False, "Expected exception"
109+
110+
89111
# This *does* seem to work, only seems untestable somehow...
90112
# def test_dots(capsys):
91113
# code = r"""

0 commit comments

Comments
 (0)