From 0357d02eab8c6df2af6abb68603600b8d6a54831 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 11 Aug 1997 03:27:24 +0000 Subject: Rewrite using class, to make waiting for processes possible; by default children are waited for automatically. --- Lib/popen2.py | 110 +++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 31 deletions(-) diff --git a/Lib/popen2.py b/Lib/popen2.py index d2867c6..ae89f94 100644 --- a/Lib/popen2.py +++ b/Lib/popen2.py @@ -2,49 +2,97 @@ import os import sys import string -MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???) +MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???) -def _popen2(cmd, capturestderr=0): +_active = [] + +def _cleanup(): + for inst in _active[:]: + inst.poll() + +class Popen3: + def __init__(self, cmd, capturestderr=0): cmd = ['/bin/sh', '-c', cmd] p2cread, p2cwrite = os.pipe() c2pread, c2pwrite = os.pipe() if capturestderr: - errout, errin = os.pipe() - pid = os.fork() - if pid == 0: - # Child - os.close(0) - os.close(1) - if os.dup(p2cread) <> 0: - sys.stderr.write('popen2: bad read dup\n') - if os.dup(c2pwrite) <> 1: - sys.stderr.write('popen2: bad write dup\n') - if capturestderr: - os.close(2) - if os.dup(errin) <> 2: pass - for i in range(3, MAXFD): - try: - os.close(i) - except: pass + errout, errin = os.pipe() + self.pid = os.fork() + if self.pid == 0: + # Child + os.close(0) + os.close(1) + if os.dup(p2cread) <> 0: + sys.stderr.write('popen2: bad read dup\n') + if os.dup(c2pwrite) <> 1: + sys.stderr.write('popen2: bad write dup\n') + if capturestderr: + os.close(2) + if os.dup(errin) <> 2: pass + for i in range(3, MAXFD): try: - os.execv(cmd[0], cmd) - finally: - os._exit(1) - # Shouldn't come here, I guess + os.close(i) + except: pass + try: + os.execv(cmd[0], cmd) + finally: os._exit(1) + # Shouldn't come here, I guess + os._exit(1) os.close(p2cread) - tochild = os.fdopen(p2cwrite, 'w') + self.tochild = os.fdopen(p2cwrite, 'w') os.close(c2pwrite) - fromchild = os.fdopen(c2pread, 'r') + self.fromchild = os.fdopen(c2pread, 'r') if capturestderr: - os.close(errin) - childerr = os.fdopen(errout, 'r') - return fromchild, tochild, childerr + os.close(errin) + self.childerr = os.fdopen(errout, 'r') else: - return fromchild, tochild, None + self.childerr = None + self.sts = -1 # Child not completed yet + _active.append(self) + def poll(self): + if self.sts < 0: + try: + pid, sts = os.waitpid(self.pid, os.WNOHANG) + if pid == self.pid: + self.sts = sts + _active.remove(self) + except os.error: + pass + return self.sts + def wait(self): + pid, sts = os.waitpid(self.pid, 0) + if pid == self.pid: + self.sts = sts + _active.remove(self) + return self.sts def popen2(cmd): - return _popen2(cmd, 0)[:2] + _cleanup() + inst = Popen3(cmd, 0) + return inst.fromchild, inst.tochild def popen3(cmd): - return _popen2(cmd, 1) + _cleanup() + inst = Popen3(cmd, 1) + return inst.fromchild, inst.tochild, inst.childerr + +def _test(): + teststr = "abc\n" + print "testing popen2..." + r, w = popen2('cat') + w.write(teststr) + w.close() + assert r.read() == teststr + print "testing popen3..." + r, w, e = popen3('cat') + w.write(teststr) + w.close() + assert r.read() == teststr + assert e.read() == "" + _cleanup() + assert not _active + print "All OK" + +if __name__ == '__main__': + _test() -- cgit v0.12