]> git.phdru.name Git - bookmarks_db.git/blobdiff - subproc.py
Fix(subproc.py): Clear pid to avoid repeated killing
[bookmarks_db.git] / subproc.py
old mode 100644 (file)
new mode 100755 (executable)
index a0099c2..57a9568
@@ -1,3 +1,5 @@
+#! /usr/bin/env python
+
 """Run a subprocess and communicate with it via stdin, stdout, and stderr.
 
 Requires that platform supports, eg, posix-style 'os.pipe' and 'os.fork'
@@ -16,7 +18,7 @@ Subprocess class features:
 
 __version__ = "Revision: 1.15 "
 
-# Id: subproc.py,v 1.15 1998/12/14 20:53:16 klm Exp 
+# Id: subproc.py,v 1.15 1998/12/14 20:53:16 klm Exp
 # Originally by ken manheimer, ken.manheimer@nist.gov, jan 1995.
 
 # Prior art: Initially based python code examples demonstrating usage of pipes
@@ -40,13 +42,18 @@ __version__ = "Revision: 1.15 "
 #
 # ken.manheimer@nist.gov
 
+# This is a modified version by Oleg Broytman <phd@phdru.name>.
+# The original version is still preserved at
+# https://www.python.org/ftp/python/contrib-09-Dec-1999/System/subproc.tar.gz
 
 import sys, os, string, time, types
 import select
 import signal
 
 
-SubprocessError = 'SubprocessError'
+class SubprocessError(Exception):
+    pass
+
 # You may need to increase execvp_grace_seconds, if you have a large or slow
 # path to search:
 execvp_grace_seconds = 0.5
@@ -115,7 +122,7 @@ class Subprocess:
                 os.execvp(cmd[0], cmd)
                 os._exit(1)                     # Shouldn't get here
 
-            except os.error, e:
+            except os.error as e:
                 if self.control_stderr:
                     os.dup2(parentErr, 2)       # Reconnect to parent's stdout
                 sys.stderr.write("**execvp failed, '%s'**\n" %
@@ -133,9 +140,12 @@ class Subprocess:
             time.sleep(execvp_grace_seconds)
             try:
                 pid, err = os.waitpid(self.pid, os.WNOHANG)
-            except os.error, (errno, msg):
+            except os.error as error:
+                errno, msg = error
                 if errno == 10:
+                    self.pid = None
                     raise SubprocessError("Subprocess '%s' failed." % self.cmd)
+                self.pid = None
                 raise SubprocessError("Subprocess failed[%d]: %s" % (errno, msg))
             if pid == self.pid:
                 # child exited already
@@ -147,6 +157,7 @@ class Subprocess:
                     "child killed by signal %d with a return code of %d"
                     % (sig, rc))
                 if rc:
+                    self.pid = None
                     raise SubprocessError(
                           "child exited with return code %d" % rc)
                 # Child may have exited, but not in error, so we won't say
@@ -205,7 +216,7 @@ class Subprocess:
             got0 = self.readPendingChars(n)
             got = got + got0
             n = n - len(got0)
-        return got      
+        return got
     def readPendingChars(self, max=None):
         """Read all currently pending subprocess output as a single string."""
         return self.readbuf.readPendingChars(max)
@@ -324,7 +335,7 @@ class Subprocess:
         # Only got here if subprocess is not gone:
         raise SubprocessError(
                "Failed kill of subproc %d, '%s', with signals %s" %
-                (self.pid, self.cmd, map(lambda(x): x[0], sigs)))
+                (self.pid, self.cmd, map(lambda x: x[0], sigs)))
 
     def __del__(self):
         """Terminate the subprocess"""
@@ -400,15 +411,15 @@ class ReadBuf:
 
         got = ""
         if self.buf:
-             if (max > 0) and (len(self.buf) > max):
-                 got = self.buf[0:max]
-                 self.buf = self.buf[max:]
-             else:
-                 got, self.buf = self.buf, ''
-             return got                                         
+            if (max > 0) and (len(self.buf) > max):
+                got = self.buf[0:max]
+                self.buf = self.buf[max:]
+            else:
+                got, self.buf = self.buf, ''
+            return got
 
         if self.eof:
-             return ''
+            return ''
 
         sel = select.select([self.fd], [], [self.fd], 0)
         if sel[2]:
@@ -536,7 +547,7 @@ def record_trial(s):
     c.write(s)
     c.seek(0)
     r = c.read()
-    show = " start:\t %s\n end:\t %s\n" % (`s`, `r`)
+    show = " start:\t %s\n end:\t %s\n" % (repr(s), repr(r))
     if r != s:
         raise IOError("String distorted:\n%s" % show)
 
@@ -589,7 +600,7 @@ class Ph:
                 line = string.splitfields(line, ':')
                 it[string.strip(line[0])] = (
                     string.strip(string.join(line[1:])))
-        
+
     def getreply(self):
         """Consume next response from ph, returning list of lines or string
         err."""
@@ -642,23 +653,23 @@ class Ph:
 #############################################################################
 
 def test(p=0):
-    print("\tOpening subprocess:")
-    p = Subprocess('cat', 1)            # set to expire noisily...
-    print(p)
     print("\tOpening bogus subprocess, should fail:")
     try:
         b = Subprocess('/', 1)
         print("\tOops!  Null-named subprocess startup *succeeded*?!?")
     except SubprocessError:
         print("\t...yep, it failed.")
+    print("\tOpening cat subprocess:")
+    p = Subprocess('cat', 1)            # set to expire noisily...
+    print(p)
     print('\tWrite, then read, two newline-teriminated lines, using readline:')
     p.write('first full line written\n'); p.write('second.\n')
-    print(`p.readline()`)
-    print(`p.readline()`)
+    print(repr(p.readline()))
+    print(repr(p.readline()))
     print('\tThree lines, last sans newline, read using combination:')
     p.write('first\n'); p.write('second\n'); p.write('third, (no cr)')
     print('\tFirst line via readline:')
-    print(`p.readline()`)
+    print(repr(p.readline()))
     print('\tRest via readPendingChars:')
     print(p.readPendingChars())
     print("\tStopping then continuing subprocess (verbose):")
@@ -680,3 +691,6 @@ def test(p=0):
             del p
             print("\tDone.")
             return None
+
+if __name__ == '__main__':
+    test()