Revision 09352fa4
b/test/ganeti.utils_unittest.py | ||
---|---|---|
32 | 32 |
import socket |
33 | 33 |
import shutil |
34 | 34 |
import re |
35 |
import select |
|
35 | 36 |
|
36 | 37 |
import ganeti |
37 | 38 |
import testutils |
... | ... | |
45 | 46 |
from ganeti.errors import LockError, UnitParseError, GenericError, \ |
46 | 47 |
ProgrammerError |
47 | 48 |
|
48 |
def _ChildHandler(signal, stack): |
|
49 |
global _ChildFlag |
|
50 |
_ChildFlag = True |
|
51 |
|
|
52 | 49 |
|
53 | 50 |
class TestIsProcessAlive(unittest.TestCase): |
54 | 51 |
"""Testing case for IsProcessAlive""" |
55 | 52 |
|
56 |
def setUp(self): |
|
57 |
global _ChildFlag |
|
58 |
# create a (most probably) non-existing process-id |
|
59 |
self.pid_non_existing = os.fork() |
|
60 |
if self.pid_non_existing == 0: |
|
61 |
os._exit(0) |
|
62 |
elif self.pid_non_existing > 0: |
|
63 |
os.waitpid(self.pid_non_existing, 0) |
|
64 |
else: |
|
65 |
raise SystemError("can't fork") |
|
66 |
_ChildFlag = False |
|
67 |
# Use _ChildHandler for SIGCHLD |
|
68 |
self.chldOrig = signal.signal(signal.SIGCHLD, _ChildHandler) |
|
53 |
def _CreateZombie(self): |
|
69 | 54 |
# create a zombie |
70 |
self.pid_zombie = os.fork() |
|
71 |
if self.pid_zombie == 0: |
|
55 |
r_fd, w_fd = os.pipe() |
|
56 |
pid_zombie = os.fork() |
|
57 |
if pid_zombie == 0: |
|
58 |
# explicit close of read, write end will be closed only due to exit |
|
59 |
os.close(r_fd) |
|
72 | 60 |
os._exit(0) |
73 |
elif self.pid_zombie < 0:
|
|
61 |
elif pid_zombie < 0: |
|
74 | 62 |
raise SystemError("can't fork") |
75 |
|
|
76 |
def tearDown(self): |
|
77 |
signal.signal(signal.SIGCHLD, self.chldOrig) |
|
63 |
# parent: we close our end of the w_fd, so reads will error as |
|
64 |
# soon as the OS cleans the child's filedescriptors on its exit |
|
65 |
os.close(w_fd) |
|
66 |
# wait for 60 seconds at max for the exit (pathological case, just |
|
67 |
# so that the test doesn't hang indefinitely) |
|
68 |
r_set, w_set, e_set = select.select([r_fd], [], [], 60) |
|
69 |
if not r_set and not e_set: |
|
70 |
self.fail("Timeout exceeded in zombie creation") |
|
71 |
return pid_zombie |
|
78 | 72 |
|
79 | 73 |
def testExists(self): |
80 | 74 |
mypid = os.getpid() |
... | ... | |
82 | 76 |
"can't find myself running") |
83 | 77 |
|
84 | 78 |
def testZombie(self): |
85 |
global _ChildFlag |
|
86 |
timeout = 10 |
|
87 |
|
|
88 |
while not _ChildFlag: |
|
89 |
if timeout >= 0: |
|
90 |
time.sleep(0.2) |
|
91 |
timeout -= 0.2 |
|
92 |
else: |
|
93 |
self.fail("timed out waiting for child's signal") |
|
94 |
break # not executed... |
|
95 |
|
|
96 |
self.assert_(not IsProcessAlive(self.pid_zombie), |
|
97 |
"zombie not detected as zombie") |
|
79 |
pid_zombie = self._CreateZombie() |
|
80 |
is_zombie = not IsProcessAlive(pid_zombie) |
|
81 |
self.assert_(is_zombie, "zombie not detected as zombie") |
|
82 |
os.waitpid(pid_zombie, os.WNOHANG) |
|
98 | 83 |
|
99 | 84 |
def testNotExisting(self): |
100 |
self.assert_(not IsProcessAlive(self.pid_non_existing), |
|
101 |
"noexisting process detected") |
|
85 |
pid_non_existing = os.fork() |
|
86 |
if pid_non_existing == 0: |
|
87 |
os._exit(0) |
|
88 |
elif pid_non_existing < 0: |
|
89 |
raise SystemError("can't fork") |
|
90 |
os.waitpid(pid_non_existing, 0) |
|
91 |
self.assert_(not IsProcessAlive(pid_non_existing), |
|
92 |
"nonexisting process detected") |
|
102 | 93 |
|
103 | 94 |
|
104 | 95 |
class TestPidFileFunctions(unittest.TestCase): |
Also available in: Unified diff