diff options
author | jquast <contact@jeffquast.com> | 2014-06-07 21:35:16 -0700 |
---|---|---|
committer | jquast <contact@jeffquast.com> | 2014-06-07 21:35:16 -0700 |
commit | 6e454ece1448b2dc6cf43a86fc01a5f3a1ae2803 (patch) | |
tree | e6381ade571b3e541c7148f4e61288c1310ef0c9 | |
parent | eb2f818015157e74d300d271bcd0e0575c4df97e (diff) | |
download | pexpect-git-6e454ece1448b2dc6cf43a86fc01a5f3a1ae2803.tar.gz |
Document and detect EOF condition in interact()
-rw-r--r-- | doc/history.rst | 3 | ||||
-rw-r--r-- | pexpect/__init__.py | 41 |
2 files changed, 18 insertions, 26 deletions
diff --git a/doc/history.rst b/doc/history.rst index 81ad48b..5b26521 100644 --- a/doc/history.rst +++ b/doc/history.rst @@ -14,6 +14,9 @@ Version 3.3 * Removed the ``pexpect.psh`` module. This was never documented, and we found no evidence that people use it. The new :mod:`pexpect.replwrap` module provides a more flexible alternative. +* Fixed issue where EOF was not correctly detected in ``interact()``, causing + a repeating loop of output on Linux, and blocking before EOF on BSD and + Solaris (:ghissue:`49`). Version 3.2 ``````````` diff --git a/pexpect/__init__.py b/pexpect/__init__.py index f27e3fe..2ce0b9d 100644 --- a/pexpect/__init__.py +++ b/pexpect/__init__.py @@ -911,12 +911,14 @@ class spawn(object): if self.child_fd in r: try: s = os.read(self.child_fd, size) - except OSError: - # Linux does this - self.flag_eof = True - raise EOF('End Of File (EOF). Exception style platform.') + except OSError, err: + if err.args[0] == errno.EIO: + # Linux-style EOF + self.flag_eof = True + raise EOF('End Of File (EOF). Exception style platform.') + raise if s == b'': - # BSD style + # BSD-style EOF self.flag_eof = True raise EOF('End Of File (EOF). Empty string style platform.') @@ -1072,23 +1074,6 @@ class spawn(object): called at the beginning of a line. This method does not send a newline. It is the responsibility of the caller to ensure the eof is sent at the beginning of a line. ''' - - ### Hmmm... how do I send an EOF? - ###C if ((m = write(pty, *buf, p - *buf)) < 0) - ###C return (errno == EWOULDBLOCK) ? n : -1; - #fd = sys.stdin.fileno() - #old = termios.tcgetattr(fd) # remember current state - #attr = termios.tcgetattr(fd) - #attr[3] = attr[3] | termios.ICANON # ICANON must be set to see EOF - #try: # use try/finally to ensure state gets restored - # termios.tcsetattr(fd, termios.TCSADRAIN, attr) - # if hasattr(termios, 'CEOF'): - # os.write(self.child_fd, '%c' % termios.CEOF) - # else: - # # Silly platform does not define CEOF so assume CTRL-D - # os.write(self.child_fd, '%c' % 4) - #finally: # restore state - # termios.tcsetattr(fd, termios.TCSADRAIN, old) if hasattr(termios, 'VEOF'): char = ord(termios.tcgetattr(self.child_fd)[6][termios.VEOF]) else: @@ -1641,10 +1626,14 @@ class spawn(object): if self.child_fd in r: try: data = self.__interact_read(self.child_fd) - except OSError as e: - # The subprocess may have closed before we get to reading it - if e.errno != errno.EIO: - raise + except OSError, err: + if err.args[0] == errno.EIO: + # Linux-style EOF + break + raise + if data == b'': + # BSD-style EOF + break if output_filter: data = output_filter(data) if self.logfile is not None: |