From ff5251bc6dd7ef8d62e3397a05209a44039892db Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Tue, 11 Nov 2008 10:58:14 +0000
Subject: [PATCH] Add cleanup of processes to utils.KillProcess

In case the process we want to signal is our own process, and the signal
we send is a deadly one, we should also cleanup after the process.

This patch adds a new parameter waitpid to this function that does this,
and changes its unittest to pass this new parameter.

Reviewed-by: imsnah
---
 lib/utils.py                  | 20 +++++++++++++++++---
 test/ganeti.utils_unittest.py |  2 +-
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/lib/utils.py b/lib/utils.py
index 6ba50a987..4de6a1e29 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -1385,7 +1385,8 @@ def RemovePidFile(name):
     pass
 
 
-def KillProcess(pid, signal_=signal.SIGTERM, timeout=30):
+def KillProcess(pid, signal_=signal.SIGTERM, timeout=30,
+                waitpid=False):
   """Kill a process given by its pid.
 
   @type pid: int
@@ -1396,22 +1397,35 @@ def KillProcess(pid, signal_=signal.SIGTERM, timeout=30):
   @param timeout: The timeout after which, if the process is still alive,
                   a SIGKILL will be sent. If not positive, no such checking
                   will be done
+  @type waitpid: boolean
+  @param waitpid: If true, we should waitpid on this process after
+      sending signals, since it's our own child and otherwise it
+      would remain as zombie
 
   """
+  def _helper(pid, signal_, wait):
+    """Simple helper to encapsulate the kill/waitpid sequence"""
+    os.kill(pid, signal_)
+    if wait:
+      try:
+        os.waitpid(pid, os.WNOHANG)
+      except OSError:
+        pass
+
   if pid <= 0:
     # kill with pid=0 == suicide
     raise errors.ProgrammerError("Invalid pid given '%s'" % pid)
 
   if not IsProcessAlive(pid):
     return
-  os.kill(pid, signal_)
+  _helper(pid, signal_, waitpid)
   if timeout <= 0:
     return
   end = time.time() + timeout
   while time.time() < end and IsProcessAlive(pid):
     time.sleep(0.1)
   if IsProcessAlive(pid):
-    os.kill(pid, signal.SIGKILL)
+    _helper(pid, signal.SIGKILL, wait)
 
 
 def FindFile(name, search_path, test=os.path.exists):
diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py
index 21ec7c60a..ad6d44c64 100755
--- a/test/ganeti.utils_unittest.py
+++ b/test/ganeti.utils_unittest.py
@@ -139,7 +139,7 @@ class TestPidFileFunctions(unittest.TestCase):
     read_pid = utils.ReadPidFile(pid_file)
     self.failUnlessEqual(read_pid, new_pid)
     self.failUnless(utils.IsProcessAlive(new_pid))
-    utils.KillProcess(new_pid)
+    utils.KillProcess(new_pid, waitpid=True)
     self.failIf(utils.IsProcessAlive(new_pid))
     utils.RemovePidFile('child')
     self.failUnlessRaises(ProgrammerError, utils.KillProcess, 0)
-- 
GitLab