tests/killdaemons.py
author Pierre-Yves David <pierre-yves.david@fb.com>
Fri, 03 Apr 2015 11:34:02 -0700
changeset 1237 1439bc8c6785
parent 1222 88e61e45026d
permissions -rwxr-xr-x
test-inhibit: drop trailing white space
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     1
#!/usr/bin/env python
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
     2
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     3
import os, sys, time, errno, signal
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     4
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     5
if os.name =='nt':
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     6
    import ctypes
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     7
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     8
    def _check(ret, expectederr=None):
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
     9
        if ret == 0:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    10
            winerrno = ctypes.GetLastError()
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    11
            if winerrno == expectederr:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    12
                return True
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    13
            raise ctypes.WinError(winerrno)
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    14
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    15
    def kill(pid, logfn, tryhard=True):
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    16
        logfn('# Killing daemon process %d' % pid)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    17
        PROCESS_TERMINATE = 1
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    18
        PROCESS_QUERY_INFORMATION = 0x400
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    19
        SYNCHRONIZE = 0x00100000
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    20
        WAIT_OBJECT_0 = 0
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    21
        WAIT_TIMEOUT = 258
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    22
        handle = ctypes.windll.kernel32.OpenProcess(
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    23
                PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    24
                False, pid)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    25
        if handle == 0:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    26
            _check(0, 87) # err 87 when process not found
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    27
            return # process not found, already finished
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    28
        try:
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    29
            r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    30
            if r == WAIT_OBJECT_0:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    31
                pass # terminated, but process handle still available
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    32
            elif r == WAIT_TIMEOUT:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    33
                _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    34
            else:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    35
                _check(r)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    36
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    37
            # TODO?: forcefully kill when timeout
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    38
            #        and ?shorter waiting time? when tryhard==True
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    39
            r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    40
                                                       # timeout = 100 ms
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    41
            if r == WAIT_OBJECT_0:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    42
                pass # process is terminated
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    43
            elif r == WAIT_TIMEOUT:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    44
                logfn('# Daemon process %d is stuck')
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    45
            else:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    46
                _check(r) # any error
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    47
        except: #re-raises
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    48
            ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    49
            raise
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    50
        _check(ctypes.windll.kernel32.CloseHandle(handle))
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    51
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    52
else:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    53
    def kill(pid, logfn, tryhard=True):
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    54
        try:
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    55
            os.kill(pid, 0)
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    56
            logfn('# Killing daemon process %d' % pid)
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    57
            os.kill(pid, signal.SIGTERM)
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    58
            if tryhard:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    59
                for i in range(10):
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    60
                    time.sleep(0.05)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    61
                    os.kill(pid, 0)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    62
            else:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    63
                time.sleep(0.1)
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    64
                os.kill(pid, 0)
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    65
            logfn('# Daemon process %d is stuck - really killing it' % pid)
7
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    66
            os.kill(pid, signal.SIGKILL)
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    67
        except OSError, err:
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    68
            if err.errno != errno.ESRCH:
cc592295900f Add write protocol support for private.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
diff changeset
    69
                raise
1222
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    70
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    71
def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    72
    if not logfn:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    73
        logfn = lambda s: s
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    74
    # Kill off any leftover daemon processes
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    75
    try:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    76
        fp = open(pidfile)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    77
        for line in fp:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    78
            try:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    79
                pid = int(line)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    80
            except ValueError:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    81
                continue
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    82
            kill(pid, logfn, tryhard)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    83
        fp.close()
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    84
        if remove:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    85
            os.unlink(pidfile)
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    86
    except IOError:
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    87
        pass
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    88
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    89
if __name__ == '__main__':
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    90
    path, = sys.argv[1:]
88e61e45026d tests: import killdaemons.py from Mercurial 1cfded2fa1a9
Matt Harbison <matt_harbison@yahoo.com>
parents: 7
diff changeset
    91
    killdaemons(path)