tests/killdaemons.py
changeset 43076 2372284d9457
parent 37846 89793289c891
child 45830 c102b704edb5
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
     5 import os
     5 import os
     6 import signal
     6 import signal
     7 import sys
     7 import sys
     8 import time
     8 import time
     9 
     9 
    10 if os.name =='nt':
    10 if os.name == 'nt':
    11     import ctypes
    11     import ctypes
    12 
    12 
    13     _BOOL = ctypes.c_long
    13     _BOOL = ctypes.c_long
    14     _DWORD = ctypes.c_ulong
    14     _DWORD = ctypes.c_ulong
    15     _UINT = ctypes.c_uint
    15     _UINT = ctypes.c_uint
    44         SYNCHRONIZE = 0x00100000
    44         SYNCHRONIZE = 0x00100000
    45         WAIT_OBJECT_0 = 0
    45         WAIT_OBJECT_0 = 0
    46         WAIT_TIMEOUT = 258
    46         WAIT_TIMEOUT = 258
    47         WAIT_FAILED = _DWORD(0xFFFFFFFF).value
    47         WAIT_FAILED = _DWORD(0xFFFFFFFF).value
    48         handle = ctypes.windll.kernel32.OpenProcess(
    48         handle = ctypes.windll.kernel32.OpenProcess(
    49                 PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
    49             PROCESS_TERMINATE | SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
    50                 False, pid)
    50             False,
       
    51             pid,
       
    52         )
    51         if handle is None:
    53         if handle is None:
    52             _check(0, 87) # err 87 when process not found
    54             _check(0, 87)  # err 87 when process not found
    53             return # process not found, already finished
    55             return  # process not found, already finished
    54         try:
    56         try:
    55             r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
    57             r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
    56             if r == WAIT_OBJECT_0:
    58             if r == WAIT_OBJECT_0:
    57                 pass # terminated, but process handle still available
    59                 pass  # terminated, but process handle still available
    58             elif r == WAIT_TIMEOUT:
    60             elif r == WAIT_TIMEOUT:
    59                 _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
    61                 _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
    60             elif r == WAIT_FAILED:
    62             elif r == WAIT_FAILED:
    61                 _check(0)  # err stored in GetLastError()
    63                 _check(0)  # err stored in GetLastError()
    62 
    64 
    63             # TODO?: forcefully kill when timeout
    65             # TODO?: forcefully kill when timeout
    64             #        and ?shorter waiting time? when tryhard==True
    66             #        and ?shorter waiting time? when tryhard==True
    65             r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
    67             r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
    66                                                        # timeout = 100 ms
    68             # timeout = 100 ms
    67             if r == WAIT_OBJECT_0:
    69             if r == WAIT_OBJECT_0:
    68                 pass # process is terminated
    70                 pass  # process is terminated
    69             elif r == WAIT_TIMEOUT:
    71             elif r == WAIT_TIMEOUT:
    70                 logfn('# Daemon process %d is stuck')
    72                 logfn('# Daemon process %d is stuck')
    71             elif r == WAIT_FAILED:
    73             elif r == WAIT_FAILED:
    72                 _check(0)  # err stored in GetLastError()
    74                 _check(0)  # err stored in GetLastError()
    73         except: #re-raises
    75         except:  # re-raises
    74             ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
    76             ctypes.windll.kernel32.CloseHandle(handle)  # no _check, keep error
    75             raise
    77             raise
    76         _check(ctypes.windll.kernel32.CloseHandle(handle))
    78         _check(ctypes.windll.kernel32.CloseHandle(handle))
    77 
    79 
       
    80 
    78 else:
    81 else:
       
    82 
    79     def kill(pid, logfn, tryhard=True):
    83     def kill(pid, logfn, tryhard=True):
    80         try:
    84         try:
    81             os.kill(pid, 0)
    85             os.kill(pid, 0)
    82             logfn('# Killing daemon process %d' % pid)
    86             logfn('# Killing daemon process %d' % pid)
    83             os.kill(pid, signal.SIGTERM)
    87             os.kill(pid, signal.SIGTERM)
    92             os.kill(pid, signal.SIGKILL)
    96             os.kill(pid, signal.SIGKILL)
    93         except OSError as err:
    97         except OSError as err:
    94             if err.errno != errno.ESRCH:
    98             if err.errno != errno.ESRCH:
    95                 raise
    99                 raise
    96 
   100 
       
   101 
    97 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
   102 def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
    98     if not logfn:
   103     if not logfn:
    99         logfn = lambda s: s
   104         logfn = lambda s: s
   100     # Kill off any leftover daemon processes
   105     # Kill off any leftover daemon processes
   101     try:
   106     try:
   105                 try:
   110                 try:
   106                     pid = int(line)
   111                     pid = int(line)
   107                     if pid <= 0:
   112                     if pid <= 0:
   108                         raise ValueError
   113                         raise ValueError
   109                 except ValueError:
   114                 except ValueError:
   110                     logfn('# Not killing daemon process %s - invalid pid'
   115                     logfn(
   111                           % line.rstrip())
   116                         '# Not killing daemon process %s - invalid pid'
       
   117                         % line.rstrip()
       
   118                     )
   112                     continue
   119                     continue
   113                 pids.append(pid)
   120                 pids.append(pid)
   114         for pid in pids:
   121         for pid in pids:
   115             kill(pid, logfn, tryhard)
   122             kill(pid, logfn, tryhard)
   116         if remove:
   123         if remove:
   117             os.unlink(pidfile)
   124             os.unlink(pidfile)
   118     except IOError:
   125     except IOError:
   119         pass
   126         pass
   120 
   127 
       
   128 
   121 if __name__ == '__main__':
   129 if __name__ == '__main__':
   122     if len(sys.argv) > 1:
   130     if len(sys.argv) > 1:
   123         path, = sys.argv[1:]
   131         (path,) = sys.argv[1:]
   124     else:
   132     else:
   125         path = os.environ["DAEMON_PIDS"]
   133         path = os.environ["DAEMON_PIDS"]
   126 
   134 
   127     killdaemons(path, remove=True)
   135     killdaemons(path, remove=True)