[PATCH 1/2] sb/execute.py: Open subprocess I/O handles in text mode

Anders Montonen Anders.Montonen at iki.fi
Wed May 6 23:37:32 UTC 2020


With a UTF-8 locale, _readthread() would occasionally split a multibyte
code point. When running under Python 3, this would trigger an
UnicodeDecodeError, which resulted in the build hanging. Solve this
issue by opening the subprocess streams in text mode, and let Python's
runtime deal with the nitty-gritty of returning complete code points.

Fixes:
Exception in thread _stderr[]:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/anders/work/rtems/rsb/source-builder/sb/execute.py", line 204, in _readthread
    data = data.decode(sys.stdout.encoding)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 4094-4095: unexpected end of data

Signed-off-by: Anders Montonen <Anders.Montonen at iki.fi>
---
 source-builder/sb/execute.py | 24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/source-builder/sb/execute.py b/source-builder/sb/execute.py
index 06f9b7d..092267b 100755
--- a/source-builder/sb/execute.py
+++ b/source-builder/sb/execute.py
@@ -123,11 +123,6 @@ class execute(object):
             is a timeout check."""
             if trace_threads:
                 print('execute:_writethread: start')
-            encoding = True
-            try:
-                tmp = bytes('temp', sys.stdin.encoding)
-            except:
-                encoding = False
             input_types = [str, bytes]
             try:
                 # Unicode is not valid in python3, not added to the list
@@ -143,8 +138,6 @@ class execute(object):
                         print('execute:_writethread: input returned:', type(lines))
                     if type(lines) in input_types:
                         try:
-                            if encoding:
-                                lines = bytes(lines, sys.stdin.encoding)
                             fh.write(lines)
                             fh.flush()
                         except:
@@ -192,16 +185,13 @@ class execute(object):
                     # and the process is shutting down.
                     #
                     try:
-                        data = fh.read1(4096)
+                        data = fh.read(4096)
                     except:
                         data = ''
                     if len(data) == 0:
                         if len(line) > 0:
                             _output_line(line + '\n', exe, prefix, out, count)
                         break
-                    # str and bytes are the same type in Python2
-                    if type(data) is not str and type(data) is bytes:
-                        data = data.decode(sys.stdout.encoding)
                     last_ch = data[-1]
                     sd = (line + data).split('\n')
                     if last_ch != '\n':
@@ -267,7 +257,7 @@ class execute(object):
                                              name = '_stdout[%s]' % (name),
                                              args = (self,
                                                      io.open(proc.stdout.fileno(),
-                                                             mode = 'rb',
+                                                             mode = 'r',
                                                              closefd = False),
                                                      self.output,
                                                      ''))
@@ -278,7 +268,7 @@ class execute(object):
                                              name = '_stderr[%s]' % (name),
                                              args = (self,
                                                      io.open(proc.stderr.fileno(),
-                                                             mode = 'rb',
+                                                             mode = 'r',
                                                              closefd = False),
                                                      self.output,
                                                      self.error_prefix))
@@ -381,7 +371,8 @@ class execute(object):
                                     cwd = cwd, env = env,
                                     stdin = stdin, stdout = stdout,
                                     stderr = stderr,
-                                    close_fds = False)
+                                    close_fds = False,
+                                    universal_newlines=True)
             if not capture:
                 return (0, proc)
             if self.output is None:
@@ -563,10 +554,7 @@ if __name__ == "__main__":
         if ec == 0:
             print('piping input into ' + commands['pipe'][0] + ': ' + \
                   commands['pipe'][2])
-            try:
-                out = bytes(commands['pipe'][2], sys.stdin.encoding)
-            except:
-                out = commands['pipe'][2]
+            out = commands['pipe'][2]
             proc.stdin.write(out)
             proc.stdin.close()
             e.capture(proc)
-- 
2.25.1



More information about the devel mailing list