[FIX] EOF handling, more fixes needed

This commit is contained in:
Benedek Racz 2020-01-23 09:29:49 +01:00
parent a0b37ebf28
commit 1ad1ea28b0
4 changed files with 41 additions and 5 deletions

View File

@ -11,7 +11,7 @@ from .console_reader import ConsoleReaderPipe
from .spawn import SpawnSocket from .spawn import SpawnSocket
from .spawn import SpawnPipe from .spawn import SpawnPipe
from .spawn import SpawnSocket as spawn from .spawn import SpawnPipe as spawn
from .spawn import run from .spawn import run
__all__ = ['split_command_line', 'join_args', 'ExceptionPexpect', 'EOF', 'TIMEOUT', __all__ = ['split_command_line', 'join_args', 'ExceptionPexpect', 'EOF', 'TIMEOUT',

View File

@ -56,6 +56,7 @@ import win32pipe
import socket import socket
from .wexpect_util import init_logger from .wexpect_util import init_logger
from .wexpect_util import EOF_CHAR
# #
# System-wide constants # System-wide constants
@ -143,6 +144,7 @@ class ConsoleReaderBase:
self.terminate_child() self.terminate_child()
time.sleep(.1) time.sleep(.1)
self.send_to_host(self.readConsoleToCursor()) self.send_to_host(self.readConsoleToCursor())
self.sendeof()
time.sleep(.1) time.sleep(.1)
self.close_connection() self.close_connection()
logger.info('Console finished.') logger.info('Console finished.')
@ -427,6 +429,13 @@ class ConsoleReaderBase:
logger.debug('Start interact window') logger.debug('Start interact window')
win32gui.ShowWindow(win32console.GetConsoleWindow(), win32con.SW_SHOW) win32gui.ShowWindow(win32console.GetConsoleWindow(), win32con.SW_SHOW)
def sendeof(self):
"""This sends an EOF to the host. This sends a character which inform the host that child
has been finished, and all of it's output has been send to host.
"""
self.send_to_host(EOF_CHAR)
class ConsoleReaderSocket(ConsoleReaderBase): class ConsoleReaderSocket(ConsoleReaderBase):

View File

@ -88,6 +88,7 @@ from .wexpect_util import EOF
from .wexpect_util import TIMEOUT from .wexpect_util import TIMEOUT
from .wexpect_util import split_command_line from .wexpect_util import split_command_line
from .wexpect_util import init_logger from .wexpect_util import init_logger
from .wexpect_util import EOF_CHAR
logger = logging.getLogger('wexpect') logger = logging.getLogger('wexpect')
@ -247,7 +248,6 @@ class SpawnBase:
self.maxread = maxread # max bytes to read at one time into buffer self.maxread = maxread # max bytes to read at one time into buffer
self.delaybeforesend = 0.1 # Sets sleep time used just before sending data to child. Time in seconds. self.delaybeforesend = 0.1 # Sets sleep time used just before sending data to child. Time in seconds.
self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds. self.delayafterterminate = 0.1 # Sets delay in terminate() method to allow kernel time to update process status. Time in seconds.
self.flag_child_finished = False
self.buffer = '' # This is the read buffer. See maxread. self.buffer = '' # This is the read buffer. See maxread.
self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched. self.searchwindowsize = searchwindowsize # Anything before searchwindowsize point is preserved, but not searched.
self.interact = interact self.interact = interact
@ -778,6 +778,15 @@ class SpawnBase:
class SpawnPipe(SpawnBase): class SpawnPipe(SpawnBase):
def __init__(self, command, args=[], timeout=30, maxread=60000, searchwindowsize=None,
logfile=None, cwd=None, env=None, codepage=None, echo=True, port=4321, host='localhost', interact=False):
self.pipe = None
super().__init__(command=command, args=args, timeout=timeout, maxread=maxread,
searchwindowsize=searchwindowsize, cwd=cwd, env=env, codepage=codepage, echo=echo, interact=interact)
def connect_to_child(self): def connect_to_child(self):
pipe_name = 'wexpect_{}'.format(self.console_pid) pipe_name = 'wexpect_{}'.format(self.console_pid)
@ -831,9 +840,9 @@ class SpawnPipe(SpawnBase):
# isalive() (which checks the real child.) and try a last read on the console. To catch # isalive() (which checks the real child.) and try a last read on the console. To catch
# the last output. # the last output.
# The flag_child_finished flag shows that this is the second trial, where we raise the EOF. # The flag_child_finished flag shows that this is the second trial, where we raise the EOF.
if self.flag_child_finished: # if self.flag_child_finished:
logger.info('EOF: self.flag_child_finished') # logger.info('EOF: self.flag_child_finished')
raise EOF('self.flag_child_finished') # raise EOF('self.flag_child_finished')
if not self.isalive(): if not self.isalive():
self.flag_child_finished = True self.flag_child_finished = True
logger.info('self.isalive() == False: Child has been died, lets do a last read!') logger.info('self.isalive() == False: Child has been died, lets do a last read!')
@ -845,6 +854,12 @@ class SpawnPipe(SpawnBase):
logger.debug(f'Readed: {s}') logger.debug(f'Readed: {s}')
else: else:
logger.spam(f'Readed: {s}') logger.spam(f'Readed: {s}')
if b'\x04' in s:
self.flag_eof = True
logger.info("EOF: EOF character has been arrived")
raise EOF('EOF character has been arrived')
return s.decode() return s.decode()
except pywintypes.error as e: except pywintypes.error as e:
if e.args[0] == winerror.ERROR_BROKEN_PIPE: #109 if e.args[0] == winerror.ERROR_BROKEN_PIPE: #109
@ -944,6 +959,8 @@ class SpawnSocket(SpawnBase):
logfile=None, cwd=None, env=None, codepage=None, echo=True, port=4321, host='localhost', interact=False): logfile=None, cwd=None, env=None, codepage=None, echo=True, port=4321, host='localhost', interact=False):
self.port = port self.port = port
self.host = host self.host = host
self.sock = None
super().__init__(command=command, args=args, timeout=timeout, maxread=maxread, super().__init__(command=command, args=args, timeout=timeout, maxread=maxread,
searchwindowsize=searchwindowsize, cwd=cwd, env=env, codepage=codepage, echo=echo, interact=interact) searchwindowsize=searchwindowsize, cwd=cwd, env=env, codepage=codepage, echo=echo, interact=interact)
@ -1003,6 +1020,13 @@ class SpawnSocket(SpawnBase):
logger.debug(f'Readed: {s}') logger.debug(f'Readed: {s}')
else: else:
logger.spam(f'Readed: {s}') logger.spam(f'Readed: {s}')
if EOF_CHAR in s:
self.flag_eof = True
logger.info("EOF: EOF character has been arrived")
raise EOF('EOF character has been arrived')
except EOF: except EOF:
self.flag_eof = True self.flag_eof = True
raise raise

View File

@ -43,6 +43,9 @@ import sys
import os import os
import logging import logging
# platform does not define VEOF so assume CTRL-D
EOF_CHAR = b'\x04'
SPAM = 5 SPAM = 5
logging.addLevelName(SPAM, "SPAM") logging.addLevelName(SPAM, "SPAM")
def spam(self, message, *args, **kws): def spam(self, message, *args, **kws):