Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[chiptest] Fix UTF-8 decoding error in stdout/err #16101

Merged
merged 2 commits into from
Mar 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions scripts/tests/chiptest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@
import queue
import re
import subprocess
import sys
import threading


class LogPipe(threading.Thread):
"""Create PTY-based PIPE for IPC.

Python provides a built-in mechanism for creating comunication PIPEs for
subprocesses spawned with Popen(). However, created PIPEs will most likely
enable IO buffering in the spawned process. In order to trick such process
to flush its streams immediately, we are going to create a PIPE based on
pseudoterminal (PTY).
"""

def __init__(self, level, capture_delegate=None, name=None):
"""
Expand All @@ -32,12 +39,8 @@ def __init__(self, level, capture_delegate=None, name=None):

self.daemon = False
self.level = level
if sys.platform == 'darwin':
self.fd_read, self.fd_write = pty.openpty()
else:
self.fd_read, self.fd_write = os.pipe()

self.pipeReader = os.fdopen(self.fd_read)
self.fd_read, self.fd_write = pty.openpty()
self.reader = open(self.fd_read, encoding='utf-8', errors='ignore')
self.captured_logs = []
self.capture_delegate = capture_delegate
self.name = name
Expand All @@ -63,13 +66,20 @@ def fileno(self):

def run(self):
"""Run the thread, logging everything."""
for line in iter(self.pipeReader.readline, ''):
while True:
try:
line = self.reader.readline()
# It seems that Darwin platform returns empty string in case
# when writing side of PTY is closed (Linux raises OSError).
if line == '':
break
except OSError:
break
logging.log(self.level, line.strip('\n'))
self.captured_logs.append(line)
if self.capture_delegate:
self.capture_delegate.Log(self.name, line)

self.pipeReader.close()
self.reader.close()

def close(self):
"""Close the write end of the pipe."""
Expand Down