summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjquast <contact@jeffquast.com>2014-06-07 21:35:16 -0700
committerThomas Kluyver <takowl@gmail.com>2014-06-15 18:01:18 -0700
commitfa813aa799432d69ed5cdc6a3171c9f67066a3ba (patch)
tree561cd285979fcf9e9aecef9e5ace061ca8604355
parent33375e861600051d0e98071192a08a5d7ccf6c87 (diff)
downloadpexpect-fa813aa799432d69ed5cdc6a3171c9f67066a3ba.tar.gz
Document and detect EOF condition in interact()
-rw-r--r--doc/history.rst3
-rw-r--r--pexpect/__init__.py41
2 files changed, 18 insertions, 26 deletions
diff --git a/doc/history.rst b/doc/history.rst
index 245b24c..2b924a9 100644
--- a/doc/history.rst
+++ b/doc/history.rst
@@ -16,6 +16,9 @@ Version 3.3
provides a more flexible alternative.
* Fixed ``TypeError: got <type 'str'> ('\r\n') as pattern`` in ``readline()``
method of ``spawnu`` (:ghissue:`67`).
+* 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 5a2cacc..a6323ab 100644
--- a/pexpect/__init__.py
+++ b/pexpect/__init__.py
@@ -914,12 +914,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.')
@@ -1075,23 +1077,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:
@@ -1644,10 +1629,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: