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