tests/killdaemons.py
author Simon Heimberg <simohe@besonet.ch>
Fri, 17 Jan 2014 21:13:20 +0100
branchstable
changeset 1330 e2fe607966f6
parent 1329 10d0d9d5c0f0
child 1331 7d8bb8590b55
permissions -rw-r--r--
tests: killdaemons.py for windows waits for killed process to terminate After kill, wait for the process to terminate. When it does not in time, write a debug message similar as in other os. But no 2nd forceful attempt is done. [ original upstream message ]
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1123
17bcbb020dda tests: add killdaemons helper script
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
#!/usr/bin/env python
17bcbb020dda tests: add killdaemons helper script
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
1128
7f09e7ac63a7 killdaemons: take file argument explicitely
Patrick Mezard <patrick@mezard.eu>
parents: 1127
diff changeset
     3
import os, sys, time, errno, signal
1123
17bcbb020dda tests: add killdaemons helper script
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
     5
if os.name =='nt':
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
     6
    import ctypes
1329
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
     7
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
     8
    def _check(ret, expectederr=None):
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
     9
        if ret == 0:
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    10
            winerrno = ctypes.GetLastError()
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    11
            if winerrno == expectederr:
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    12
                return True
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    13
            raise ctypes.WinError(winerrno)
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    14
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    15
    def kill(pid, logfn, tryhard=True):
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    16
        logfn('# Killing daemon process %d' % pid)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    17
        PROCESS_TERMINATE = 1
1330
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    18
        SYNCHRONIZE = 0x00100000L
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    19
        WAIT_OBJECT_0 = 0
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    20
        WAIT_TIMEOUT = 258
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    21
        handle = ctypes.windll.kernel32.OpenProcess(
1330
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    22
                PROCESS_TERMINATE|SYNCHRONIZE, False, pid)
1329
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    23
        if handle == 0:
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    24
            # TODO: call _check(0, expected) to check if "process not found"
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    25
            return # process not found, already finished
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    26
        try:
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    27
            _check(ctypes.windll.kernel32.TerminateProcess(handle, -1), 5)
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    28
            #      windows error 5 when process does not exist or no access TODO
1330
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    29
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    30
            # TODO?: forcefully kill when timeout
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    31
            #        and ?shorter waiting time? when tryhard==True
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    32
            r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    33
                                                       # timeout = 100 ms
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    34
            if r == WAIT_OBJECT_0:
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    35
                pass # process is terminated
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    36
            elif r == WAIT_TIMEOUT:
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    37
                logfn('# Daemon process %d is stuck')
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    38
            else:
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    39
                check(r) # any error
1329
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    40
        except: #re-raises
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    41
            ctypes.windll.kernel32.CloseHandle(handle) # no _check, keep error
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    42
            raise
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    43
        _check(ctypes.windll.kernel32.CloseHandle(handle))
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    44
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    45
else:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    46
    def kill(pid, logfn, tryhard=True):
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    47
        try:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    48
            os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    49
            logfn('# Killing daemon process %d' % pid)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    50
            os.kill(pid, signal.SIGTERM)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    51
            if tryhard:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    52
                for i in range(10):
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    53
                    time.sleep(0.05)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    54
                    os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    55
            else:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    56
                time.sleep(0.1)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    57
                os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    58
            logfn('# Daemon process %d is stuck - really killing it' % pid)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    59
            os.kill(pid, signal.SIGKILL)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    60
        except OSError, err:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    61
            if err.errno != errno.ESRCH:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    62
                raise
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    63
1126
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    64
def killdaemons(pidfile, tryhard=True, remove=False, logfn=None):
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    65
    if not logfn:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    66
        logfn = lambda s: s
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    67
    # Kill off any leftover daemon processes
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    68
    try:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    69
        fp = open(pidfile)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    70
        for line in fp:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    71
            try:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    72
                pid = int(line)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    73
            except ValueError:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    74
                continue
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    75
            kill(pid, logfn, tryhard)
1126
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    76
        fp.close()
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    77
        if remove:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    78
            os.unlink(pidfile)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    79
    except IOError:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    80
        pass
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    81
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    82
if __name__ == '__main__':
1128
7f09e7ac63a7 killdaemons: take file argument explicitely
Patrick Mezard <patrick@mezard.eu>
parents: 1127
diff changeset
    83
    path, = sys.argv[1:]
7f09e7ac63a7 killdaemons: take file argument explicitely
Patrick Mezard <patrick@mezard.eu>
parents: 1127
diff changeset
    84
    killdaemons(path)
1126
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    85