From 740c5aabc85dd3a40d739f485311154ca241a71e Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Mon, 23 Jun 2008 12:50:15 +0000 Subject: [PATCH] Fix the zombie process unittest The failure is because in high load, the parent gets to run before the child has the chance to os._exit(), and therefore it is still running when the parent does the check. The fix removes the chance of this happening by waiting to receive a SIGCHLD (but not calling wait()) before trying to test the pid. Reviewed-by: imsnah --- test/ganeti.utils_unittest.py | 36 ++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py index abc4a7692..c5f8cfda6 100755 --- a/test/ganeti.utils_unittest.py +++ b/test/ganeti.utils_unittest.py @@ -28,6 +28,7 @@ import tempfile import os.path import os import md5 +import signal import socket import shutil import re @@ -43,16 +44,16 @@ from ganeti.utils import IsProcessAlive, Lock, Unlock, RunCmd, \ SetEtcHostsEntry, RemoveEtcHostsEntry from ganeti.errors import LockError, UnitParseError +def _ChildHandler(signal, stack): + global _ChildFlag + _ChildFlag = True class TestIsProcessAlive(unittest.TestCase): """Testing case for IsProcessAlive""" + def setUp(self): - # create a zombie and a (hopefully) non-existing process id - self.pid_zombie = os.fork() - if self.pid_zombie == 0: - os._exit(0) - elif self.pid_zombie < 0: - raise SystemError("can't fork") + global _ChildFlag + # create a (most probably) non-existing process-id self.pid_non_existing = os.fork() if self.pid_non_existing == 0: os._exit(0) @@ -60,7 +61,18 @@ class TestIsProcessAlive(unittest.TestCase): os.waitpid(self.pid_non_existing, 0) else: raise SystemError("can't fork") + _ChildFlag = False + # Use _ChildHandler for SIGCHLD + self.chldOrig = signal.signal(signal.SIGCHLD, _ChildHandler) + # create a zombie + self.pid_zombie = os.fork() + if self.pid_zombie == 0: + os._exit(0) + elif self.pid_zombie < 0: + raise SystemError("can't fork") + def tearDown(self): + signal.signal(signal.SIGCHLD, self.chldOrig) def testExists(self): mypid = os.getpid() @@ -68,10 +80,20 @@ class TestIsProcessAlive(unittest.TestCase): "can't find myself running") def testZombie(self): + global _ChildFlag + timeout = 10 + + while not _ChildFlag: + if timeout >= 0: + time.sleep(0.2) + timeout -= 0.2 + else: + self.fail("timed out waiting for child's signal") + break # not executed... + self.assert_(not IsProcessAlive(self.pid_zombie), "zombie not detected as zombie") - def testNotExisting(self): self.assert_(not IsProcessAlive(self.pid_non_existing), "noexisting process detected") -- GitLab