summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Kluyver <takowl@gmail.com>2014-09-04 10:44:51 -0700
committerThomas Kluyver <takowl@gmail.com>2014-09-04 10:44:51 -0700
commitae950f0b759f5ecb5237c7366e866225373afebc (patch)
tree1820dd48592d73eacb34380ece1d1562770622ae
parent9057873f9b73d216149b78c922be19fac8e3a44c (diff)
parentca35dc774df9c79a57facf42f0fa7d73a4985a1d (diff)
downloadpexpect-ae950f0b759f5ecb5237c7366e866225373afebc.tar.gz
Merge pull request #109 from pexpect/issue-86-and-100-stdin-closed
Closes issue #86 and issue #100
-rw-r--r--doc/history.rst5
-rw-r--r--pexpect/__init__.py11
-rwxr-xr-xtests/test_expect.py37
3 files changed, 49 insertions, 4 deletions
diff --git a/doc/history.rst b/doc/history.rst
index 0da6c6e..a09f124 100644
--- a/doc/history.rst
+++ b/doc/history.rst
@@ -4,6 +4,11 @@ History
Releases
--------
+Version 3.4
+```````````
+* Fixed regression when executing pexpect with some prior releases of
+ the multiprocessing module where stdin has been closed (:ghissue:`86`).
+
Version 3.3
```````````
diff --git a/pexpect/__init__.py b/pexpect/__init__.py
index 4a34f15..06dbac4 100644
--- a/pexpect/__init__.py
+++ b/pexpect/__init__.py
@@ -498,12 +498,17 @@ class spawn(object):
# inherit EOF and INTR definitions from controlling process.
try:
from termios import VEOF, VINTR
- fd = sys.__stdin__.fileno()
+ try:
+ fd = sys.__stdin__.fileno()
+ except ValueError:
+ # ValueError: I/O operation on closed file
+ fd = sys.__stdout__.fileno()
self._INTR = ord(termios.tcgetattr(fd)[6][VINTR])
self._EOF = ord(termios.tcgetattr(fd)[6][VEOF])
- except (ImportError, OSError, IOError, termios.error):
+ except (ImportError, OSError, IOError, ValueError, termios.error):
# unless the controlling process is also not a terminal,
- # such as cron(1). Fall-back to using CEOF and CINTR.
+ # such as cron(1), or when stdin and stdout are both closed.
+ # Fall-back to using CEOF and CINTR. There
try:
from termios import CEOF, CINTR
(self._INTR, self._EOF) = (CINTR, CEOF)
diff --git a/tests/test_expect.py b/tests/test_expect.py
index 8ccb9c5..3f4c9d8 100755
--- a/tests/test_expect.py
+++ b/tests/test_expect.py
@@ -18,11 +18,13 @@ PEXPECT LICENSE
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
'''
+import multiprocessing
import unittest
import subprocess
import time
import signal
import sys
+import os
import pexpect
from . import PexpectTestCase
@@ -542,7 +544,40 @@ class ExpectTestCase (PexpectTestCase.PexpectTestCase):
signal.alarm(1)
p1.expect('END')
+ def test_stdin_closed(self):
+ '''
+ Ensure pexpect continues to operate even when stdin is closed
+ '''
+ class Closed_stdin_proc(multiprocessing.Process):
+ def run(self):
+ sys.__stdin__.close()
+ cat = pexpect.spawn('cat')
+ cat.sendeof()
+ cat.expect(pexpect.EOF)
+
+ proc = Closed_stdin_proc()
+ proc.start()
+ proc.join()
+ assert proc.exitcode == 0
+
+ def test_stdin_stdout_closed(self):
+ '''
+ Ensure pexpect continues to operate even when stdin and stdout is closed
+ '''
+ class Closed_stdin_stdout_proc(multiprocessing.Process):
+ def run(self):
+ sys.__stdin__.close()
+ sys.__stdout__.close()
+ cat = pexpect.spawn('cat')
+ cat.sendeof()
+ cat.expect(pexpect.EOF)
+
+ proc = Closed_stdin_stdout_proc()
+ proc.start()
+ proc.join()
+ assert proc.exitcode == 0
+
if __name__ == '__main__':
unittest.main()
-suite = unittest.makeSuite(ExpectTestCase,'test')
+suite = unittest.makeSuite(ExpectTestCase, 'test')