Change in vdsm[master]: Introducing context manager to terminate async processes on ...

ybronhei at redhat.com ybronhei at redhat.com
Tue Jan 5 23:31:04 UTC 2016


Yaniv Bronhaim has uploaded a new change for review.

Change subject: Introducing context manager to terminate async processes on internal fail
......................................................................

Introducing context manager to terminate async processes on internal fail

part of the effort to omit the use of deathSignal.

Change-Id: I003cce39d62dba5644937fafaf2c6e24c526c075
Signed-off-by: Yaniv Bronhaim <ybronhei at redhat.com>
---
M lib/vdsm/utils.py
1 file changed, 44 insertions(+), 4 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/07/51407/1

diff --git a/lib/vdsm/utils.py b/lib/vdsm/utils.py
index 8288d5b..2a456ca 100644
--- a/lib/vdsm/utils.py
+++ b/lib/vdsm/utils.py
@@ -652,12 +652,14 @@
     if not sync:
         p = AsyncProc(p)
         if data is not None:
-            p.stdin.write(data)
-            p.stdin.flush()
+            with terminator(p, execCmdLogger):
+                p.stdin.write(data)
+                p.stdin.flush()
 
         return p
 
-    (out, err) = p.communicate(data)
+    with terminator(p, execCmdLogger):
+        (out, err) = p.communicate(data)
 
     if out is None:
         # Prevent splitlines() from barfing later on
@@ -685,7 +687,10 @@
                    nice=nice, ioclass=ioclass, execCmdLogger=execCmdLogger,
                    deathSignal=deathSignal)
 
-    if not proc.wait(cond=stop):
+    with terminator(proc, execCmdLogger):
+        finished = proc.wait(cond=stop)
+
+    if not finished:
         proc.kill()
         raise ActionStopped()
 
@@ -697,6 +702,41 @@
     return proc.returncode, out, err
 
 
+def terminator(proc, logger):
+    '''
+    A context manager for taking care for killing process on failure.
+    The first exception will be remembered and re-raised.
+
+    Sample usage:
+    proc = ExecCmd('cmd', sync=False)
+    with terminator(proc, logger) as rollback:
+        ...
+        proc.communicate()
+        ...
+    '''
+    def __init__(self, proc, log):
+        self._proc = proc
+        self._log = log
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        """
+        If this function raises exception we re-raises the original exception
+        and kill the  process finished.
+        """
+        if exc_type is None and exc_value is None:
+            return
+
+        exc_info = sys.exc_info()
+        try:
+            proc.kill()
+        except Exception:
+            self._log.error("Failed to kill subprocess")
+        six.reraise(*exc_info)
+
+
 def traceback(on="", msg="Unhandled exception"):
     """
     Log a traceback for unhandled execptions.


-- 
To view, visit https://gerrit.ovirt.org/51407
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I003cce39d62dba5644937fafaf2c6e24c526c075
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Yaniv Bronhaim <ybronhei at redhat.com>


More information about the vdsm-patches mailing list