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