Skip to content

Commit

Permalink
bugy#223: fixed an error on reading huge unicode outputs
Browse files Browse the repository at this point in the history
  • Loading branch information
bugy committed Jun 23, 2019
1 parent 3dc3fb9 commit a8c57cd
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
23 changes: 17 additions & 6 deletions src/execution/process_pty.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,19 @@ def wait_finish(self):
def pipe_process_output(self):
utf8_stream = self.encoding.lower() == 'utf-8'

buffer = b''

try:
while True:
finished = False
wait_new_output = False

max_read_bytes = 1024

data = buffer
buffer = b''

if self.is_finished():
data = b""
while True:
try:
chunk = os.read(self.pty_master, max_read_bytes)
Expand All @@ -84,9 +88,8 @@ def pipe_process_output(self):
finished = True

else:
data = ""
try:
data = os.read(self.pty_master, max_read_bytes)
data += os.read(self.pty_master, max_read_bytes)
if data.endswith(b"\r"):
data += os.read(self.pty_master, 1)

Expand All @@ -104,9 +107,17 @@ def pipe_process_output(self):
if not data:
wait_new_output = True

if utf8_stream and data:
while data and data[-1] >= 127:
buffer = bytes([data[-1]]) + buffer
data = data[:-1]

if data:
output_text = data.decode(self.encoding)
self._write_script_output(output_text)
try:
output_text = data.decode(self.encoding)
self._write_script_output(output_text)
except UnicodeDecodeError as e:
print(e)

if finished:
break
Expand All @@ -115,7 +126,7 @@ def pipe_process_output(self):
time.sleep(0.01)

except:
self._write_script_output("Unexpected error occurred. Contact the administrator.")
self._write_script_output('\nUnexpected error occurred. Contact the administrator.')

try:
self.kill()
Expand Down
Empty file added src/tests/execution/__init__.py
Empty file.
30 changes: 30 additions & 0 deletions src/tests/execution/process_pty_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import threading
import unittest

from execution.process_pty import PtyProcessWrapper
from react.observable import read_until_closed
from tests import test_utils


class TestPtyProcessWrapper(unittest.TestCase):
def test_many_unicode_characters(self):
long_unicode_text = ('ΩΨΔ\n' * 100000)
test_utils.create_file('test.txt', text=long_unicode_text)

process_wrapper = PtyProcessWrapper(['cat', 'test.txt'], test_utils.temp_folder)
process_wrapper.start()

thread = threading.Thread(target=process_wrapper.wait_finish, daemon=True)
thread.start()
thread.join(timeout=0.1)

output = ''.join(read_until_closed(process_wrapper.output_stream))
self.assertEqual(long_unicode_text, output)

self.assertEqual(0, process_wrapper.get_return_code())

def setUp(self):
test_utils.setup()

def tearDown(self):
test_utils.cleanup()

0 comments on commit a8c57cd

Please sign in to comment.