tests/killdaemons.py
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 24 Mar 2014 21:37:33 -0700
branchstable
changeset 1363 58a33a3ed565
parent 1359 e23422941bae
child 1372 8d921a12dd31
permissions -rw-r--r--
run-tests: Pass arguments into argument parser Before, arguments were not passed into the optparse.OptionParser instance and were coming from sys.argv. This patch enables consumers to define the list of arguments to parse without having to adjust sys.argv. [ 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
1332
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    18
        PROCESS_QUERY_INFORMATION = 0x400
1359
e23422941bae killdaemons: drop superfluous L suffix from constant
Augie Fackler <raf@durin42.com>
parents: 1332
diff changeset
    19
        SYNCHRONIZE = 0x00100000
1330
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    20
        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
    21
        WAIT_TIMEOUT = 258
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    22
        handle = ctypes.windll.kernel32.OpenProcess(
1332
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    23
                PROCESS_TERMINATE|SYNCHRONIZE|PROCESS_QUERY_INFORMATION,
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    24
                False, pid)
1329
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    25
        if handle == 0:
1331
7d8bb8590b55 tests: killdaemons.py for checks reason when getting no process handle
Simon Heimberg <simohe@besonet.ch>
parents: 1330
diff changeset
    26
            _check(0, 87) # err 87 when process not found
1329
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    27
            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
    28
        try:
1332
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    29
            r = ctypes.windll.kernel32.WaitForSingleObject(handle, 100)
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    30
            if r == WAIT_OBJECT_0:
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    31
                pass # terminated, but process handle still available
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    32
            elif r == WAIT_TIMEOUT:
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    33
                _check(ctypes.windll.kernel32.TerminateProcess(handle, -1))
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    34
            else:
e307d04d3c4d tests: killdaemons.py for windows distinguishes access violation and terminated
Simon Heimberg <simohe@besonet.ch>
parents: 1331
diff changeset
    35
                _check(r)
1330
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    36
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    37
            # 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
    38
            #        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
    39
            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
    40
                                                       # timeout = 100 ms
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    41
            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
    42
                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
    43
            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
    44
                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
    45
            else:
e2fe607966f6 tests: killdaemons.py for windows waits for killed process to terminate
Simon Heimberg <simohe@besonet.ch>
parents: 1329
diff changeset
    46
                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
    47
        except: #re-raises
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    48
            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
    49
            raise
10d0d9d5c0f0 tests: kill for windows in killdaemons.py checks return values
Simon Heimberg <simohe@besonet.ch>
parents: 1128
diff changeset
    50
        _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
    51
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    52
else:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    53
    def kill(pid, logfn, tryhard=True):
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    54
        try:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    55
            os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    56
            logfn('# Killing daemon process %d' % pid)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    57
            os.kill(pid, signal.SIGTERM)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    58
            if tryhard:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    59
                for i in range(10):
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    60
                    time.sleep(0.05)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    61
                    os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    62
            else:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    63
                time.sleep(0.1)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    64
                os.kill(pid, 0)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    65
            logfn('# Daemon process %d is stuck - really killing it' % pid)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    66
            os.kill(pid, signal.SIGKILL)
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    67
        except OSError, err:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    68
            if err.errno != errno.ESRCH:
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    69
                raise
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    70
1126
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    71
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
    72
    if not logfn:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    73
        logfn = lambda s: s
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    74
    # Kill off any leftover daemon processes
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    75
    try:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    76
        fp = open(pidfile)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    77
        for line in fp:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    78
            try:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    79
                pid = int(line)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    80
            except ValueError:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    81
                continue
1127
79d7aa832cf4 killdaemons: add windows implementation
Patrick Mezard <patrick@mezard.eu>
parents: 1126
diff changeset
    82
            kill(pid, logfn, tryhard)
1126
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    83
        fp.close()
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    84
        if remove:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    85
            os.unlink(pidfile)
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    86
    except IOError:
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    87
        pass
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    88
dbcb11553a3b run-tests: do not duplicate killdaemons() code
Patrick Mezard <patrick@mezard.eu>
parents: 1125
diff changeset
    89
if __name__ == '__main__':
1128
7f09e7ac63a7 killdaemons: take file argument explicitely
Patrick Mezard <patrick@mezard.eu>
parents: 1127
diff changeset
    90
    path, = sys.argv[1:]
7f09e7ac63a7 killdaemons: take file argument explicitely
Patrick Mezard <patrick@mezard.eu>
parents: 1127
diff changeset
    91
    killdaemons(path)