Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

_win.py 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # -*- coding: utf-8 -*-
  2. """
  3. billiard._win
  4. ~~~~~~~~~~~~~
  5. Windows utilities to terminate process groups.
  6. """
  7. from __future__ import absolute_import
  8. import os
  9. # psutil is painfully slow in win32. So to avoid adding big
  10. # dependencies like pywin32 a ctypes based solution is preferred
  11. # Code based on the winappdbg project http://winappdbg.sourceforge.net/
  12. # (BSD License)
  13. from ctypes import (
  14. byref, sizeof, windll,
  15. Structure, WinError, POINTER,
  16. c_size_t, c_char, c_void_p,
  17. )
  18. from ctypes.wintypes import DWORD, LONG
  19. ERROR_NO_MORE_FILES = 18
  20. INVALID_HANDLE_VALUE = c_void_p(-1).value
  21. class PROCESSENTRY32(Structure):
  22. _fields_ = [
  23. ('dwSize', DWORD),
  24. ('cntUsage', DWORD),
  25. ('th32ProcessID', DWORD),
  26. ('th32DefaultHeapID', c_size_t),
  27. ('th32ModuleID', DWORD),
  28. ('cntThreads', DWORD),
  29. ('th32ParentProcessID', DWORD),
  30. ('pcPriClassBase', LONG),
  31. ('dwFlags', DWORD),
  32. ('szExeFile', c_char * 260),
  33. ]
  34. LPPROCESSENTRY32 = POINTER(PROCESSENTRY32)
  35. def CreateToolhelp32Snapshot(dwFlags=2, th32ProcessID=0):
  36. hSnapshot = windll.kernel32.CreateToolhelp32Snapshot(dwFlags,
  37. th32ProcessID)
  38. if hSnapshot == INVALID_HANDLE_VALUE:
  39. raise WinError()
  40. return hSnapshot
  41. def Process32First(hSnapshot, pe=None):
  42. return _Process32n(windll.kernel32.Process32First, hSnapshot, pe)
  43. def Process32Next(hSnapshot, pe=None):
  44. return _Process32n(windll.kernel32.Process32Next, hSnapshot, pe)
  45. def _Process32n(fun, hSnapshot, pe=None):
  46. if pe is None:
  47. pe = PROCESSENTRY32()
  48. pe.dwSize = sizeof(PROCESSENTRY32)
  49. success = fun(hSnapshot, byref(pe))
  50. if not success:
  51. if windll.kernel32.GetLastError() == ERROR_NO_MORE_FILES:
  52. return
  53. raise WinError()
  54. return pe
  55. def get_all_processes_pids():
  56. """Return a dictionary with all processes pids as keys and their
  57. parents as value. Ignore processes with no parents.
  58. """
  59. h = CreateToolhelp32Snapshot()
  60. parents = {}
  61. pe = Process32First(h)
  62. while pe:
  63. if pe.th32ParentProcessID:
  64. parents[pe.th32ProcessID] = pe.th32ParentProcessID
  65. pe = Process32Next(h, pe)
  66. return parents
  67. def get_processtree_pids(pid, include_parent=True):
  68. """Return a list with all the pids of a process tree"""
  69. parents = get_all_processes_pids()
  70. all_pids = list(parents.keys())
  71. pids = set([pid])
  72. while 1:
  73. pids_new = pids.copy()
  74. for _pid in all_pids:
  75. if parents[_pid] in pids:
  76. pids_new.add(_pid)
  77. if pids_new == pids:
  78. break
  79. pids = pids_new.copy()
  80. if not include_parent:
  81. pids.remove(pid)
  82. return list(pids)
  83. def kill_processtree(pid, signum):
  84. """Kill a process and all its descendants"""
  85. family_pids = get_processtree_pids(pid)
  86. for _pid in family_pids:
  87. os.kill(_pid, signum)