-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmonkeypatch_psutil.py
114 lines (101 loc) · 4.49 KB
/
monkeypatch_psutil.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env python
"""
This file is intended to make psutil behave portable on the wintendo, and
to enable functionality the upstream author doesn't think ready to use.
"""
import platform
import signal
import subprocess
import time
# import sys
winver = platform.win32_ver()
if winver[0]:
WINDOWS = True
POSIX = False
# may throw on elderly wintendos?
# this is only here on the wintendo, don't bother me else where.
# pylint: disable=no-name-in-module
from psutil import Process
from psutil import TimeoutExpired
from psutil import _psutil_windows as cext
from psutil._pswindows import WindowsService
class WindowsServiceMonkey(WindowsService):
"""
We want this code anyways, its good enough!
actions
XXX: the necessary C bindings for start() and stop() are
implemented but for now I prefer not to expose them.
I may change my mind in the future. Reasons:
- they require Administrator privileges
- can't implement a timeout for stop() (unless by using a thread,
which sucks)
- would require adding ServiceAlreadyStarted and
ServiceAlreadyStopped exceptions, adding two new APIs.
- we might also want to have modify(), which would basically mean
rewriting win32serviceutil.ChangeServiceConfig, which involves a
lot of stuff (and API constants which would pollute the API), see:
http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/
win32/lib/win32serviceutil.py.html#0175
- psutil is typically about "read only" monitoring stuff;
win_service_* APIs should only be used to retrieve a service and
check whether it's running
"""
def start(self, timeout=None):
"""start a windows service"""
with self._wrap_exceptions():
cext.winservice_start(self.name())
if timeout:
giveup_at = time.time() + timeout
while True:
if self.status() == "running":
return
if time.time() > giveup_at:
raise TimeoutExpired(timeout)
time.sleep(0.1)
def stop(self):
"""stop windows service"""
# Note: timeout is not implemented because it's just not
# possible, see:
# http://stackoverflow.com/questions/11973228/
with self._wrap_exceptions():
return cext.winservice_stop(self.name())
WindowsService.start = WindowsServiceMonkey.start
WindowsService.stop = WindowsServiceMonkey.stop
class ProcessMonkey(Process):
"""overload this function"""
def terminate(self):
"""Terminate the process with SIGTERM pre-emptively checking
whether PID has been reused.
On Windows this will only work for processes spawned through psutil
or started using
kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP.
"""
if POSIX:
self._send_signal(signal.SIGTERM)
else: # pragma: no cover
# def sigint_boomerang_handler(signum, frame):
# """do the right thing to behave like linux does"""
# # pylint: disable=unused-argument
# if signum != signal.SIGINT:
# sys.exit(1)
# # pylint: disable=unnecessary-pass
# pass
#
# original_sigint_handler = signal.getsignal(signal.SIGINT)
# signal.signal(signal.SIGINT, sigint_boomerang_handler)
# # only here on the wintendo:
# # pylint: disable=no-member
# self.send_signal(signal.CTRL_BREAK_EVENT)
self.wait()
# restore original handler
# signal.signal(signal.SIGINT, original_sigint_handler)
Process.terminate = ProcessMonkey.terminate
# pylint: disable=super-init-not-called disable=consider-using-with
class Popen(Process):
"""overload this function"""
def __init__(self, *args, **kwargs):
kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP
self.__subproc = subprocess.Popen(*args, **kwargs)
self._init(self.__subproc.pid, _ignore_nsp=True)
from psutil import Popen as patchme_popen
patchme_popen.__init__ = Popen.__init__