Runtime: Add stderr support to local posix spawn based subprocess replacement
authorEdouard Tisserant
Fri, 24 Nov 2023 12:16:19 +0100
changeset 3860 a1d7187b8402
parent 3859 098875cff39f
child 3861 7e17f7e02a2b
Runtime: Add stderr support to local posix spawn based subprocess replacement
runtime/spawn_subprocess.py
--- a/runtime/spawn_subprocess.py	Wed Nov 22 11:24:16 2023 +0100
+++ b/runtime/spawn_subprocess.py	Fri Nov 24 12:16:19 2023 +0100
@@ -14,17 +14,24 @@
 
 
 class Popen(object):
-    def __init__(self, args, stdin=None, stdout=None):
+    def __init__(self, args, stdin=None, stdout=None, stderr=None):
         self.returncode = None
         self.stdout = None
+        self.stderr = None
         self.stdin = None
-        # TODO: stderr
         file_actions = posix_spawn.FileActions()
         if stdout is not None:
             # child's stdout, child 2 parent pipe
+            c1pread, c1pwrite = os.pipe()
+            # attach child's stdout to writing en of c1p pipe
+            file_actions.add_dup2(c1pwrite, 1)
+            # close other end
+            file_actions.add_close(c1pread)
+        if stderr is not None:
+            # child's stderr, child 2 parent pipe
             c2pread, c2pwrite = os.pipe()
-            # attach child's stdout to writing en of c2p pipe
-            file_actions.add_dup2(c2pwrite, 1)
+            # attach child's stderr to writing en of c2p pipe
+            file_actions.add_dup2(c2pwrite, 2)
             # close other end
             file_actions.add_close(c2pread)
         if stdin is not None:
@@ -36,7 +43,10 @@
             file_actions.add_close(p2cwrite)
         self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions)
         if stdout is not None:
-            self.stdout = os.fdopen(c2pread)
+            self.stdout = os.fdopen(c1pread)
+            os.close(c1pwrite)
+        if stderr is not None:
+            self.stderr = os.fdopen(c2pread)
             os.close(c2pwrite)
         if stdin is not None:
             self.stdin = os.fdopen(p2cwrite, 'w')
@@ -50,29 +60,44 @@
         if self.stdin is not None:
             self.stdin.close()
             self.stdin = None
+
         if self.stdout is not None:
             stdoutdata = self.stdout.read()
         else:
             stdoutdata = ""
 
-        # TODO
-        stderrdata = ""
+        if self.stderr is not None:
+            stderrdata = self.stderr.read()
+        else:
+            stderrdata = ""
 
         self._wait()
+
         if self.stdout is not None:
             self.stdout.close()
             self.stdout = None
 
+        if self.stderr is not None:
+            self.stderr.close()
+            self.stderr = None
+
         return (stdoutdata, stderrdata)
 
     def wait(self):
         if self.stdin is not None:
             self.stdin.close()
             self.stdin = None
+
         self._wait()
+
         if self.stdout is not None:
             self.stdout.close()
             self.stdout = None
+
+        if self.stderr is not None:
+            self.stderr.close()
+            self.stderr = None
+
         return self.returncode
 
     def poll(self):
@@ -84,10 +109,15 @@
                 if self.stdin is not None:
                     self.stdin.close()
                     self.stdin = None
+
                 if self.stdout is not None:
                     self.stdout.close()
                     self.stdout = None
 
+                if self.stderr is not None:
+                    self.stderr.close()
+                    self.stderr = None
+
         return self.returncode
 
     def kill(self):
@@ -96,10 +126,15 @@
         if self.stdin is not None:
             self.stdin.close()
             self.stdin = None
+
         if self.stdout is not None:
             self.stdout.close()
             self.stdout = None
 
+        if self.stderr is not None:
+            self.stderr.close()
+            self.stderr = None
+
 
 def call(*args):
     cmd = []