From 5e8d9331e31c876b9ae89f5b2707b5e7c178af0e Mon Sep 17 00:00:00 2001 Message-Id: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 09:24:30 +0200 Subject: [PATCH 1/6] Bug #34593 ucs-test/UMC/top: Document wait4() Organization: Univention GmbH, Bremen, Germany Assign to dummy variables instead of using magic [1] --- .../test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 6a613be..7da8a41 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -65,7 +65,7 @@ class TestUMCProcessKilling(TestUMCSystem): print("Created process with pid '%s' was not terminated, " "forcing kill" % self.Proc.pid) self.Proc.kill() - exit_status = wait4(self.Proc.pid, WNOHANG)[1] + _pid, exit_status, _res_usage = wait4(self.Proc.pid, WNOHANG) if exit_status != 9: print("The exit status while force kill is '%s' " "instead of 'SIGKILL' code 9." % exit_status) @@ -97,7 +97,7 @@ class TestUMCProcessKilling(TestUMCSystem): pid = self.create_process() if self.query_process_exists(pid): self.make_kill_request('SIGTERM', [pid]) - exit_status = wait4(pid, WNOHANG)[1] + _pid, exit_status, _res_usage = wait4(pid, WNOHANG) if exit_status != 15: utils.fail("Process exit status is '%s' instead of " "'SIGTERM' code 15." % exit_status) @@ -115,7 +115,7 @@ class TestUMCProcessKilling(TestUMCSystem): pid = self.create_process() if self.query_process_exists(pid): self.make_kill_request('SIGKILL', [pid]) - exit_status = wait4(pid, WNOHANG)[1] + _pid, exit_status, _res_usage = wait4(pid, WNOHANG) if exit_status != 9: utils.fail("Process exit status is '%s' instead of " "'SIGKILL' code 9." % exit_status) -- 1.9.1 From 1b0a5d2c781b8f7a69a840a6c70c84e30ea7f425 Mon Sep 17 00:00:00 2001 Message-Id: <1b0a5d2c781b8f7a69a840a6c70c84e30ea7f425.1402484679.git.hahn@univention.de> In-Reply-To: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> References: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 09:45:31 +0200 Subject: [PATCH 2/6] Bug #34593 ucs-test/UMC/top: Error details Organization: Univention GmbH, Bremen, Germany Use %r instead of %s for dumping UMC request. Print missing key. --- .../test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 7da8a41..12ef028 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -53,9 +53,9 @@ class TestUMCProcessKilling(TestUMCSystem): if 'python' in result['command']: return True except KeyError as exc: - utils.fail("Failed to find 'pid' or 'command' keys in" - "the 'top/query' request respone from UMC: %s" - % result) + utils.fail("Failed to find key '%s' in" + "the 'top/query' request respone from UMC: %r" + % (exc, result)) def force_process_kill(self): """ -- 1.9.1 From 02f4720ed431dd5354f39bad8433a92c11560f89 Mon Sep 17 00:00:00 2001 Message-Id: <02f4720ed431dd5354f39bad8433a92c11560f89.1402484679.git.hahn@univention.de> In-Reply-To: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> References: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 09:43:29 +0200 Subject: [PATCH 3/6] Bug #34593 ucs-test/UMC/top: signal Organization: Univention GmbH, Bremen, Germany Use signal.SIG* instead of magic numbers. Use os.WTERMSIG() to only check signal number. --- .../60_umc-system/22_umc-service-proc-killing | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 12ef028..1bb7936 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -8,8 +8,8 @@ sys.path.insert(0, '.') from TestUMCSystemModule import TestUMCSystem from psutil import Process -from os import wait4, WNOHANG -from subprocess import Popen +from os import wait4, WNOHANG, WTERMSIG +import signal from univention.config_registry import ConfigRegistry import univention.testing.utils as utils @@ -66,9 +66,9 @@ class TestUMCProcessKilling(TestUMCSystem): "forcing kill" % self.Proc.pid) self.Proc.kill() _pid, exit_status, _res_usage = wait4(self.Proc.pid, WNOHANG) - if exit_status != 9: - print("The exit status while force kill is '%s' " - "instead of 'SIGKILL' code 9." % exit_status) + if WTERMSIG(exit_status) != signal.SIGKILL: + print("The exit status while force kill is 0x%x " + "instead of 'SIGKILL'(%d)." % (exit_status, signal.SIGKILL)) def create_process(self): """ @@ -98,9 +98,9 @@ class TestUMCProcessKilling(TestUMCSystem): if self.query_process_exists(pid): self.make_kill_request('SIGTERM', [pid]) _pid, exit_status, _res_usage = wait4(pid, WNOHANG) - if exit_status != 15: - utils.fail("Process exit status is '%s' instead of " - "'SIGTERM' code 15." % exit_status) + if WTERMSIG(exit_status) != signal.SIGTERM: + utils.fail("Process exit status is 0x%x instead of " + "SIGTERM(%d)." % (exit_status, signal.SIGTERM)) if self.query_process_exists(pid): utils.fail("Process did not terminate after request " "with 'SIGTERM' signal") @@ -116,9 +116,9 @@ class TestUMCProcessKilling(TestUMCSystem): if self.query_process_exists(pid): self.make_kill_request('SIGKILL', [pid]) _pid, exit_status, _res_usage = wait4(pid, WNOHANG) - if exit_status != 9: - utils.fail("Process exit status is '%s' instead of " - "'SIGKILL' code 9." % exit_status) + if WTERMSIG(exit_status) != signal.SIGKILL: + utils.fail("Process exit status is 0x%x instead of " + "SIGKILL(%d)." % (exit_status, signal.SIGKILL)) if self.query_process_exists(pid): utils.fail("Process did not terminate after request " "with 'SIGKILL' signal") -- 1.9.1 From 65804abb7d08af3075675a6cba689b0c6772000d Mon Sep 17 00:00:00 2001 Message-Id: <65804abb7d08af3075675a6cba689b0c6772000d.1402484679.git.hahn@univention.de> In-Reply-To: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> References: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 10:00:13 +0200 Subject: [PATCH 4/6] Bug #34593 ucs-test/UMC/top: Common code Organization: Univention GmbH, Bremen, Germany Extract common test code into separate function. --- .../60_umc-system/22_umc-service-proc-killing | 49 +++++++++------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 1bb7936..76019b2 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -83,49 +83,38 @@ class TestUMCProcessKilling(TestUMCSystem): self.Proc = Process(pid) return pid - def main(self): - """ - Method to start the test of the UMC backend - process killing functionality. - """ - self.get_ucr_credentials() - self.create_connection_authenticate() - - # case 1: killing process using signal 'SIGTERM' + def test(self, signame): + print "Testing UMC process killing with signal '%s'" % signame + signum = getattr(signal, signame) try: - print "Testing UMC process killing with 'SIGTERM' signal" pid = self.create_process() if self.query_process_exists(pid): - self.make_kill_request('SIGTERM', [pid]) + self.make_kill_request(signame, [pid]) _pid, exit_status, _res_usage = wait4(pid, WNOHANG) - if WTERMSIG(exit_status) != signal.SIGTERM: + if WTERMSIG(exit_status) != signum: utils.fail("Process exit status is 0x%x instead of " - "SIGTERM(%d)." % (exit_status, signal.SIGTERM)) + "%s(%d)." % (exit_status, signame, signum)) if self.query_process_exists(pid): utils.fail("Process did not terminate after request " - "with 'SIGTERM' signal") + "with signal %s" % (signame)) else: utils.fail("The process is not running right after creation") finally: self.force_process_kill() + def main(self): + """ + Method to start the test of the UMC backend + process killing functionality. + """ + self.get_ucr_credentials() + self.create_connection_authenticate() + + # case 1: killing process using signal 'SIGTERM' + self.test('SIGTERM') + # case 2: killing process using signal 'SIGKILL' - try: - print "Testing UMC process killing with 'SIGKILL' signal" - pid = self.create_process() - if self.query_process_exists(pid): - self.make_kill_request('SIGKILL', [pid]) - _pid, exit_status, _res_usage = wait4(pid, WNOHANG) - if WTERMSIG(exit_status) != signal.SIGKILL: - utils.fail("Process exit status is 0x%x instead of " - "SIGKILL(%d)." % (exit_status, signal.SIGKILL)) - if self.query_process_exists(pid): - utils.fail("Process did not terminate after request " - "with 'SIGKILL' signal") - else: - utils.fail("The process is not running right after creation") - finally: - self.force_process_kill() + self.test('SIGKILL') if __name__ == '__main__': -- 1.9.1 From eb75c06d934ae5e69428f4953d7a089fec28b5ed Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> References: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 09:45:31 +0200 Subject: [PATCH 5/6] Bug #34593 ucs-test/UMC/top: use fork() Organization: Univention GmbH, Bremen, Germany Use os.fork() instead of subprocess.Popen() to allow SIGTERM to be ignored. --- .../60_umc-system/22_umc-service-proc-killing | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 76019b2..20c620a 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -8,8 +8,9 @@ sys.path.insert(0, '.') from TestUMCSystemModule import TestUMCSystem from psutil import Process -from os import wait4, WNOHANG, WTERMSIG +from os import wait4, WNOHANG, WTERMSIG, fork import signal +from time import sleep from univention.config_registry import ConfigRegistry import univention.testing.utils as utils @@ -50,7 +51,7 @@ class TestUMCProcessKilling(TestUMCSystem): for result in request_result: try: if result['pid'] == pid: - if 'python' in result['command']: + if sys.executable in result['command']: return True except KeyError as exc: utils.fail("Failed to find key '%s' in" @@ -70,18 +71,21 @@ class TestUMCProcessKilling(TestUMCSystem): print("The exit status while force kill is 0x%x " "instead of 'SIGKILL'(%d)." % (exit_status, signal.SIGKILL)) - def create_process(self): + def create_process(self, ignore_sigterm=False): """ Initiates a simple test process that should be killed after. Creates a psutil Process class to check running state before terminating. Also returns process id (pid). """ - proc = Popen(['python', - '-c', - 'from time import sleep \nsleep(30)']) - pid = proc.pid - self.Proc = Process(pid) - return pid + pid = fork() + if pid: # parent + self.Proc = Process(pid) + return pid + else: # child under test + if ignore_sigterm: + signal.signal(signal.SIGTERM, signal.SIG_IGN) + sleep(30) + sys.exit(0) def test(self, signame): print "Testing UMC process killing with signal '%s'" % signame -- 1.9.1 From b7cd99c18fbfb2953135d401ac8eeefc3a553df1 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> References: <5e8d9331e31c876b9ae89f5b2707b5e7c178af0e.1402484679.git.hahn@univention.de> From: Philipp Hahn Date: Wed, 11 Jun 2014 09:45:31 +0200 Subject: [PATCH 6/6] Bug #34593 ucs-test/UMC/top: Masked SIGTERM Organization: Univention GmbH, Bremen, Germany Add test for masked SIGTERM. --- .../ucs-test/tests/60_umc-system/22_umc-service-proc-killing | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing index 20c620a..ea74d6c 100755 --- a/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing +++ b/branches/ucs-3.2/ucs-3.2-2/test/ucs-test/tests/60_umc-system/22_umc-service-proc-killing @@ -57,6 +57,7 @@ class TestUMCProcessKilling(TestUMCSystem): utils.fail("Failed to find key '%s' in" "the 'top/query' request respone from UMC: %r" % (exc, result)) + return False def force_process_kill(self): """ @@ -87,18 +88,18 @@ class TestUMCProcessKilling(TestUMCSystem): sleep(30) sys.exit(0) - def test(self, signame): + def test(self, signame, ignore_signal=False): print "Testing UMC process killing with signal '%s'" % signame signum = getattr(signal, signame) try: - pid = self.create_process() + pid = self.create_process(ignore_signal) if self.query_process_exists(pid): self.make_kill_request(signame, [pid]) _pid, exit_status, _res_usage = wait4(pid, WNOHANG) - if WTERMSIG(exit_status) != signum: + if ignore_signal != (WTERMSIG(exit_status) != signum): utils.fail("Process exit status is 0x%x instead of " "%s(%d)." % (exit_status, signame, signum)) - if self.query_process_exists(pid): + if ignore_signal != self.query_process_exists(pid): utils.fail("Process did not terminate after request " "with signal %s" % (signame)) else: @@ -120,6 +121,9 @@ class TestUMCProcessKilling(TestUMCSystem): # case 2: killing process using signal 'SIGKILL' self.test('SIGKILL') + # case 3: killing unwilling process using signal 'SIGTERM' + self.test('SIGTERM', ignore_signal=True) + if __name__ == '__main__': TestUMC = TestUMCProcessKilling() -- 1.9.1