Revision b2a1f511
b/lib/utils.py | ||
---|---|---|
1092 | 1092 |
pass |
1093 | 1093 |
|
1094 | 1094 |
|
1095 |
def KillProcess(pid, signal=signal.SIGTERM, timeout=30): |
|
1096 |
"""Kill a process given by its pid. |
|
1097 |
|
|
1098 |
@type pid: int |
|
1099 |
@param pid: The PID to terminate. |
|
1100 |
@type signal: int |
|
1101 |
@param signal: The signal to send, by default SIGTERM |
|
1102 |
@type timeout: int |
|
1103 |
@param timeout: The timeout after which, if the process is still alive, |
|
1104 |
a SIGKILL will be sent. If not positive, no such checking |
|
1105 |
will be done |
|
1106 |
|
|
1107 |
""" |
|
1108 |
if pid <= 0: |
|
1109 |
# kill with pid=0 == suicide |
|
1110 |
raise errors.ProgrammerError("Invalid pid given '%s'" % pid) |
|
1111 |
|
|
1112 |
if not IsProcessAlive(pid): |
|
1113 |
return |
|
1114 |
os.kill(pid, signal) |
|
1115 |
if timeout <= 0: |
|
1116 |
return |
|
1117 |
end = time.time() + timeout |
|
1118 |
while time.time() < end and IsProcessAlive(pid): |
|
1119 |
time.sleep(0.1) |
|
1120 |
if IsProcessAlive(pid): |
|
1121 |
os.kill(pid, signal.SIGKILL) |
|
1122 |
|
|
1123 |
|
|
1095 | 1124 |
def FindFile(name, search_path, test=os.path.exists): |
1096 | 1125 |
"""Look for a filesystem object in a given path. |
1097 | 1126 |
|
b/test/ganeti.utils_unittest.py | ||
---|---|---|
43 | 43 |
ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \ |
44 | 44 |
ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \ |
45 | 45 |
SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree |
46 |
from ganeti.errors import LockError, UnitParseError, GenericError |
|
46 |
from ganeti.errors import LockError, UnitParseError, GenericError, \ |
|
47 |
ProgrammerError |
|
47 | 48 |
|
48 | 49 |
def _ChildHandler(signal, stack): |
49 | 50 |
global _ChildFlag |
... | ... | |
132 | 133 |
self.failIf(os.path.exists(pid_file), |
133 | 134 |
"PID file should not exist anymore") |
134 | 135 |
|
136 |
def testKill(self): |
|
137 |
pid_file = self.f_dpn('child') |
|
138 |
r_fd, w_fd = os.pipe() |
|
139 |
new_pid = os.fork() |
|
140 |
if new_pid == 0: #child |
|
141 |
utils.WritePidFile('child') |
|
142 |
os.write(w_fd, 'a') |
|
143 |
signal.pause() |
|
144 |
os._exit(0) |
|
145 |
return |
|
146 |
# else we are in the parent |
|
147 |
# wait until the child has written the pid file |
|
148 |
os.read(r_fd, 1) |
|
149 |
read_pid = utils.ReadPidFile(pid_file) |
|
150 |
self.failUnlessEqual(read_pid, new_pid) |
|
151 |
self.failUnless(utils.IsProcessAlive(new_pid)) |
|
152 |
utils.KillProcess(new_pid) |
|
153 |
self.failIf(utils.IsProcessAlive(new_pid)) |
|
154 |
utils.RemovePidFile('child') |
|
155 |
self.failUnlessRaises(ProgrammerError, utils.KillProcess, 0) |
|
156 |
|
|
135 | 157 |
def tearDown(self): |
136 | 158 |
for name in os.listdir(self.dir): |
137 | 159 |
os.unlink(os.path.join(self.dir, name)) |
Also available in: Unified diff