1 """Windows service. Requires pywin32."""
2
3 import os
4 import win32api
5 import win32con
6 import win32event
7 import win32service
8 import win32serviceutil
9
10 from cherrypy.process import wspbus, plugins
11
12
14 """A WSPBus plugin for handling Win32 console events (like Ctrl-C)."""
15
19
21 if self.is_set:
22 self.bus.log('Handler for console events already set.', level=40)
23 return
24
25 result = win32api.SetConsoleCtrlHandler(self.handle, 1)
26 if result == 0:
27 self.bus.log('Could not SetConsoleCtrlHandler (error %r)' %
28 win32api.GetLastError(), level=40)
29 else:
30 self.bus.log('Set handler for console events.', level=40)
31 self.is_set = True
32
34 if not self.is_set:
35 self.bus.log('Handler for console events already off.', level=40)
36 return
37
38 try:
39 result = win32api.SetConsoleCtrlHandler(self.handle, 0)
40 except ValueError:
41
42 result = 1
43
44 if result == 0:
45 self.bus.log('Could not remove SetConsoleCtrlHandler (error %r)' %
46 win32api.GetLastError(), level=40)
47 else:
48 self.bus.log('Removed handler for console events.', level=40)
49 self.is_set = False
50
52 """Handle console control events (like Ctrl-C)."""
53 if event in (win32con.CTRL_C_EVENT, win32con.CTRL_LOGOFF_EVENT,
54 win32con.CTRL_BREAK_EVENT, win32con.CTRL_SHUTDOWN_EVENT,
55 win32con.CTRL_CLOSE_EVENT):
56 self.bus.log('Console event %s: shutting down bus' % event)
57
58
59 try:
60 self.stop()
61 except ValueError:
62 pass
63
64 self.bus.exit()
65
66 return 1
67 return 0
68
69
71 """A Web Site Process Bus implementation for Win32.
72
73 Instead of time.sleep, this bus blocks using native win32event objects.
74 """
75
79
81 """Return a win32event for the given state (creating it if needed)."""
82 try:
83 return self.events[state]
84 except KeyError:
85 event = win32event.CreateEvent(None, 0, 0,
86 "WSPBus %s Event (pid=%r)" %
87 (state.name, os.getpid()))
88 self.events[state] = event
89 return event
90
94 self._state = value
95 event = self._get_state_event(value)
96 win32event.PulseEvent(event)
97 state = property(_get_state, _set_state)
98
99 - def wait(self, state, interval=0.1, channel=None):
100 """Wait for the given state(s), KeyboardInterrupt or SystemExit.
101
102 Since this class uses native win32event objects, the interval
103 argument is ignored.
104 """
105 if isinstance(state, (tuple, list)):
106
107 if self.state not in state:
108 events = tuple([self._get_state_event(s) for s in state])
109 win32event.WaitForMultipleObjects(events, 0, win32event.INFINITE)
110 else:
111
112 if self.state != state:
113 event = self._get_state_event(state)
114 win32event.WaitForSingleObject(event, win32event.INFINITE)
115
116
118 """Control codes used to "signal" a service via ControlService.
119
120 User-defined control codes are in the range 128-255. We generally use
121 the standard Python value for the Linux signal and add 128. Example:
122
123 >>> signal.SIGUSR1
124 10
125 control_codes['graceful'] = 128 + 10
126 """
127
129 """For the given value, return its corresponding key."""
130 for key, val in self.items():
131 if val is obj:
132 return key
133 raise ValueError("The given object could not be found: %r" % obj)
134
135 control_codes = _ControlCodes({'graceful': 138})
136
137
139 if command == 'stop':
140 win32serviceutil.StopService(service)
141 elif command == 'restart':
142 win32serviceutil.RestartService(service)
143 else:
144 win32serviceutil.ControlService(service, control_codes[command])
145
146
171
172
173 if __name__ == '__main__':
174 win32serviceutil.HandleCommandLine(PyWebService)
175