diff options
author | Matthew Blecker <matthewb@chromium.org> | 2018-10-16 12:51:11 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-18 10:55:36 -0700 |
commit | 58d06c4e513e035f15710e7f176fa8e39bcda5e6 (patch) | |
tree | 54fc9af59769074a9d84ae03ccb92dfacd482b04 | |
parent | 530a68d904c74a1e509e3b952fa094fab9551dc1 (diff) | |
download | chrome-ec-58d06c4e513e035f15710e7f176fa8e39bcda5e6.tar.gz |
ec3po console and interpreter: Handle EOFError from the pipes.
EOF is expected sometimes upon shutdown, when one thread (console or
interpreter) manages to close its write side of a pipe before the other
thread receives the shutdown pipe unblocked notification. EOF is now
considered another indication to shutdown.
BRANCH=none
BUG=b:79684405
TEST=With this change plus CL:1279145 to switch to threading, I am no
longer able to reproduce the formerly occasional EOFError tracebacks upon
shutdown, with either ctrl+c or SIGTERM. Basic servod functionality
continues to work, including dut-control ec_uart_pty, servo_console_pty
(both tested with minicom), dut_i2c_mux, enable_ite_dfu, get_ite_chipid.
Testing performed with a servo_micro connected to an octopus_ite. I tested
both without and with CL:1279145 i.e. both with subprocesses and with
threads (though I only ever encountered EOFError with the latter).
Change-Id: Iaa1ddc5f05a32ef806fa5f84d0ed0ad4739189ce
Signed-off-by: Matthew Blecker <matthewb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1284509
Reviewed-by: Nick Sanders <nsanders@chromium.org>
Reviewed-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org>
-rwxr-xr-x | util/ec3po/console.py | 83 | ||||
-rw-r--r-- | util/ec3po/interpreter.py | 16 |
2 files changed, 70 insertions, 29 deletions
diff --git a/util/ec3po/console.py b/util/ec3po/console.py index 61d2315e7c..66ed9ea53b 100755 --- a/util/ec3po/console.py +++ b/util/ec3po/console.py @@ -443,6 +443,9 @@ class Console(object): Returns: is_enhanced: A boolean indicating whether the EC responded to the interrogation correctly. + + Raises: + EOFError: Allowed to propagate through from self.dbg_pipe.recv(). """ # Send interrogation byte and wait for the response. self.logger.debug('Performing interrogation.') @@ -476,6 +479,10 @@ class Console(object): Args: byte: An integer representing the character received from the user. + + Raises: + EOFError: Allowed to propagate through from self.CheckForEnhancedECImage() + i.e. from self.dbg_pipe.recv(). """ fd = self.master_pty @@ -876,8 +883,15 @@ def StartLoop(console, command_active, shutdown_pipe=None): console.logger.debug('Input from user: %s, locked:%s', str(line).strip(), command_active.value) for i in line: - # Handle each character as it arrives. - console.HandleChar(i) + try: + # Handle each character as it arrives. + console.HandleChar(i) + except EOFError: + console.logger.debug( + 'ec3po console received EOF from dbg_pipe in HandleChar()' + ' while reading console.master_pty') + continue_looping = False + break except OSError: console.logger.debug('Ptm read failed, probably user disconnect.') @@ -889,34 +903,51 @@ def StartLoop(console, command_active, shutdown_pipe=None): console.logger.debug('Input from interface: %s, locked:%s', str(line).strip(), command_active.value) for i in line: - # Handle each character as it arrives. - console.HandleChar(i) + try: + # Handle each character as it arrives. + console.HandleChar(i) + except EOFError: + console.logger.debug( + 'ec3po console received EOF from dbg_pipe in HandleChar()' + ' while reading console.interface_pty') + continue_looping = False + break elif obj is console.cmd_pipe: - data = console.cmd_pipe.recv() - # Write it to the user console. - console.logger.debug('|CMD|-%s->\'%s\'', - ('u' if master_connected else '') + - ('i' if command_active.value else ''), data.strip()) - if master_connected: - os.write(console.master_pty, data) - if command_active.value: - os.write(console.interface_pty, data) - - elif obj is console.dbg_pipe: - data = console.dbg_pipe.recv() - if console.interrogation_mode == 'auto': - # Search look buffer for enhanced EC image string. - console.CheckBufferForEnhancedImage(data) - # Write it to the user console. - if len(data) > 1: - console.logger.debug('|DBG|-%s->\'%s\'', + try: + data = console.cmd_pipe.recv() + except EOFError: + console.logger.debug('ec3po console received EOF from cmd_pipe') + continue_looping = False + else: + # Write it to the user console. + console.logger.debug('|CMD|-%s->\'%s\'', ('u' if master_connected else '') + ('i' if command_active.value else ''), data.strip()) - if master_connected: - os.write(console.master_pty, data) - if command_active.value: - os.write(console.interface_pty, data) + if master_connected: + os.write(console.master_pty, data) + if command_active.value: + os.write(console.interface_pty, data) + + elif obj is console.dbg_pipe: + try: + data = console.dbg_pipe.recv() + except EOFError: + console.logger.debug('ec3po console received EOF from dbg_pipe') + continue_looping = False + else: + if console.interrogation_mode == 'auto': + # Search look buffer for enhanced EC image string. + console.CheckBufferForEnhancedImage(data) + # Write it to the user console. + if len(data) > 1: + console.logger.debug('|DBG|-%s->\'%s\'', + ('u' if master_connected else '') + + ('i' if command_active.value else ''), data.strip()) + if master_connected: + os.write(console.master_pty, data) + if command_active.value: + os.write(console.interface_pty, data) elif obj is shutdown_pipe: console.logger.debug( diff --git a/util/ec3po/interpreter.py b/util/ec3po/interpreter.py index fd811716de..86272f6646 100644 --- a/util/ec3po/interpreter.py +++ b/util/ec3po/interpreter.py @@ -347,7 +347,11 @@ class Interpreter(object): self.dbg_pipe.send(data) def HandleUserData(self): - """Handle any incoming commands from the user.""" + """Handle any incoming commands from the user. + + Raises: + EOFError: Allowed to propagate through from self.cmd_pipe.recv(). + """ self.logger.log(1, 'Command data available. Begin processing.') data = self.cmd_pipe.recv() # Process the command. @@ -418,11 +422,17 @@ def StartLoop(interp, shutdown_pipe=None): # Handle any commands from the user. elif obj is interp.cmd_pipe: - interp.HandleUserData() + try: + interp.HandleUserData() + except EOFError: + interp.logger.debug( + 'ec3po interpreter received EOF from cmd_pipe in ' + 'HandleUserData()') + continue_looping = False elif obj is shutdown_pipe: interp.logger.debug( - 'ec3po console received shutdown pipe unblocked notification') + 'ec3po interpreter received shutdown pipe unblocked notification') continue_looping = False for obj in writeable: |