summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjquast <contact@jeffquast.com>2014-06-07 21:35:16 -0700
committerjquast <contact@jeffquast.com>2014-06-07 21:35:16 -0700
commit6e454ece1448b2dc6cf43a86fc01a5f3a1ae2803 (patch)
treee6381ade571b3e541c7148f4e61288c1310ef0c9
parenteb2f818015157e74d300d271bcd0e0575c4df97e (diff)
downloadpexpect-git-6e454ece1448b2dc6cf43a86fc01a5f3a1ae2803.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 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: