[elbe-devel] [PATCH 3/4] elbepack: log: manage pipes within async_logging()

Thomas Weißschuh thomas.weissschuh at linutronix.de
Fri Apr 26 16:25:38 CEST 2024


Now that the caller does not need to dup() the write fd before calling
async_logging(), the pipe can be completely managed within the log
framework.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
 elbepack/log.py         | 11 +++++------
 elbepack/rpcaptcache.py |  8 +++-----
 elbepack/shellhelper.py | 24 ++++++++++--------------
 3 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/elbepack/log.py b/elbepack/log.py
index c47d9ea03e2a..662a2bcbd24a 100644
--- a/elbepack/log.py
+++ b/elbepack/log.py
@@ -223,12 +223,11 @@ def close_logging():
 
 class AsyncLogging(threading.Thread):
 
-    def __init__(self, atmost, stream, block, r, w):
+    def __init__(self, atmost, stream, block):
         super().__init__(daemon=True)
         self.lines = []
         self.atmost = atmost
-        self.read_fd = r
-        self.write_fd = w
+        self.read_fd, self.write_fd = os.pipe()
         calling_thread = threading.current_thread().ident
         extra = {'_thread': calling_thread}
         extra['context'] = ''
@@ -284,8 +283,8 @@ class AsyncLogging(threading.Thread):
             self.block.info('\n'.join(self.lines))
 
 
-def async_logging(r, w, stream, block, atmost=4096):
-    t = AsyncLogging(atmost, stream, block, r, w)
+def async_logging(stream, block, atmost=4096):
+    t = AsyncLogging(atmost, stream, block)
     t.start()
     return t
 
@@ -294,7 +293,7 @@ def async_logging(r, w, stream, block, atmost=4096):
 def async_logging_ctx(*args, **kwargs):
     t = async_logging(*args, **kwargs)
     try:
-        yield
+        yield t.write_fd
     finally:
         t.shutdown()
         t.join()
diff --git a/elbepack/rpcaptcache.py b/elbepack/rpcaptcache.py
index cb9f71804c01..5a7e71302183 100644
--- a/elbepack/rpcaptcache.py
+++ b/elbepack/rpcaptcache.py
@@ -41,9 +41,8 @@ class MyMan(BaseManager):
         return _register
 
     @staticmethod
-    def redirect_outputs(r, w):
+    def redirect_outputs(w):
         """Redirect all outputs to the writing end of a pipe 'w'"""
-        os.close(r)
         os.dup2(w, os.sys.stdout.fileno())
         os.dup2(w, os.sys.stderr.fileno())
         # Buffering of 1 because in Python3 buffering of 0 is illegal
@@ -55,10 +54,9 @@ class MyMan(BaseManager):
 
     def start(self):
         """Redirect outputs of the process to an async logging thread"""
-        r, w = os.pipe()
-        alog = async_logging(r, w, soap, log)
+        alog = async_logging(soap, log)
         self.log_finalizer = Finalize(self, alog.shutdown)
-        super(MyMan, self).start(MyMan.redirect_outputs, [r, w])
+        super(MyMan, self).start(MyMan.redirect_outputs, [alog.write_fd])
 
 
 class InChRootObject:
diff --git a/elbepack/shellhelper.py b/elbepack/shellhelper.py
index d998e7c62ac4..11be6f06b89a 100644
--- a/elbepack/shellhelper.py
+++ b/elbepack/shellhelper.py
@@ -69,14 +69,12 @@ def do(cmd, allow_fail=False, stdin=None, env_add=None, log_cmd=None):
 
     logging.info(log_cmd or _log_cmd(cmd), extra={'context': '[CMD] '})
 
-    r, w = os.pipe()
+    with async_logging_ctx(soap, log) as w:
+        if stdin is None:
+            p = Popen(cmd, shell=shell, stdout=w, stderr=STDOUT, env=new_env)
+        else:
+            p = Popen(cmd, shell=shell, stdin=PIPE, stdout=w, stderr=STDOUT, env=new_env)
 
-    if stdin is None:
-        p = Popen(cmd, shell=shell, stdout=w, stderr=STDOUT, env=new_env)
-    else:
-        p = Popen(cmd, shell=shell, stdin=PIPE, stdout=w, stderr=STDOUT, env=new_env)
-
-    with async_logging_ctx(r, w, soap, log):
         p.communicate(input=stdin)
 
     if p.returncode and not allow_fail:
@@ -153,14 +151,12 @@ def get_command_out(cmd, stdin=None, allow_fail=False, env_add=None):
 
     logging.info(_log_cmd(cmd), extra={'context': '[CMD] '})
 
-    r, w = os.pipe()
-
-    if stdin is None:
-        p = Popen(cmd, shell=shell, stdout=PIPE, stderr=w, env=new_env)
-    else:
-        p = Popen(cmd, shell=shell, stdin=PIPE, stdout=PIPE, stderr=w, env=new_env)
+    with async_logging_ctx(soap, log) as w:
+        if stdin is None:
+            p = Popen(cmd, shell=shell, stdout=PIPE, stderr=w, env=new_env)
+        else:
+            p = Popen(cmd, shell=shell, stdin=PIPE, stdout=PIPE, stderr=w, env=new_env)
 
-    with async_logging_ctx(r, w, soap, log):
         stdout, _ = p.communicate(input=stdin)
 
     if p.returncode and not allow_fail:

-- 
2.44.0



More information about the elbe-devel mailing list