PageRenderTime 71ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/killdaemons.py

https://bitbucket.org/mirror/mercurial/
Python | 91 lines | 78 code | 8 blank | 5 comment | 26 complexity | f88d23281b69d76b87baddd5d1d1245d MD5 | raw file
Possible License(s): GPL-2.0
  1. #!/usr/bin/env python
  2. import os, sys, time, errno, signal
  3. if os.name =='nt':
  4. import ctypes
  5. def _check(ret, expectederr=None):
  6. if ret == 0:
  7. winerrno = ctypes.GetLastError()
  8. if winerrno == expectederr:
  9. return True
  10. raise ctypes.WinError(winerrno)
  11. def kill(pid, logfn, tryhard=True):
  12. logfn('# Killing daemon process %d' % pid)
  13. PROCESS_TERMINATE = 1
  14. PROCESS_QUERY_INFORMATION = 0x400
  15. SYNCHRONIZE = 0x00100000
  16. WAIT_OBJECT_0 = 0
  17. WAIT_TIMEOUT = 258
  18. handle = ctypes.windll.kernel32.OpenProcess(
  19. PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
  20. False, pid)
  21. if handle == 0:
  22. _check(0, 87) # err 87 when process not found
  23. return # process not found, already finished
  24. try:
  25. r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
  26. if r == WAIT_OBJECT_0:
  27. pass # terminated, but process handle still available
  28. elif r == WAIT_TIMEOUT:
  29. _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
  30. else:
  31. _check(r)
  32. # TODO?: forcefully kill when timeout
  33. # and ?shorter waiting time? when tryhard==True
  34. r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
  35. # timeout = 100 ms
  36. if r == WAIT_OBJECT_0:
  37. pass # process is terminated
  38. elif r == WAIT_TIMEOUT:
  39. logfn('# Daemon process %d is stuck')
  40. else:
  41. _check(r) # any error
  42. except: #re-raises
  43. ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
  44. raise
  45. _check(ctypes.windll.kernel32.CloseHandle(handle))
  46. else:
  47. def kill(pid, logfn, tryhard=True):
  48. try:
  49. os.kill(pid, 0)
  50. logfn('# Killing daemon process %d' % pid)
  51. os.kill(pid, signal.SIGTERM)
  52. if tryhard:
  53. for i in range(10):
  54. time.sleep(0.05)
  55. os.kill(pid, 0)
  56. else:
  57. time.sleep(0.1)
  58. os.kill(pid, 0)
  59. logfn('# Daemon process %d is stuck - really killing it' % pid)
  60. os.kill(pid, signal.SIGKILL)
  61. except OSError, err:
  62. if err.errno != errno.ESRCH:
  63. raise
  64. def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
  65. if not logfn:
  66. logfn = lambda s: s
  67. # Kill off any leftover daemon processes
  68. try:
  69. fp = open(pidfile)
  70. for line in fp:
  71. try:
  72. pid = int(line)
  73. except ValueError:
  74. continue
  75. kill(pid, logfn, tryhard)
  76. fp.close()
  77. if remove:
  78. os.unlink(pidfile)
  79. except IOError:
  80. pass
  81. if __name__ == '__main__':
  82. path, = sys.argv[1:]
  83. killdaemons(path)