1 """Windows service. Requires pywin32."""
2
3 import os
4 import thread
5 import win32api
6 import win32con
7 import win32event
8 import win32service
9 import win32serviceutil
10
11 from cherrypy.process import wspbus, plugins
12
13
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 """A Web Site Process Bus implementation for Win32.
73
74 Instead of time.sleep, this bus blocks using native win32event objects.
75 """
76
80
82 """Return a win32event for the given state (creating it if needed)."""
83 try:
84 return self.events[state]
85 except KeyError:
86 event = win32event.CreateEvent(None, 0, 0,
87 u"WSPBus %s Event (pid=%r)" %
88 (state.name, os.getpid()))
89 self.events[state] = event
90 return event
91
95 self._state = value
96 event = self._get_state_event(value)
97 win32event.PulseEvent(event)
98 state = property(_get_state, _set_state)
99
100 - def wait(self, state, interval=0.1):
101 """Wait for the given state(s), KeyboardInterrupt or SystemExit.
102
103 Since this class uses native win32event objects, the interval
104 argument is ignored.
105 """
106 if isinstance(state, (tuple, list)):
107
108 if self.state not in state:
109 events = tuple([self._get_state_event(s) for s in state])
110 win32event.WaitForMultipleObjects(events, 0, win32event.INFINITE)
111 else:
112
113 if self.state != state:
114 event = self._get_state_event(state)
115 win32event.WaitForSingleObject(event, win32event.INFINITE)
116
117
119 """Control codes used to "signal" a service via ControlService.
120
121 User-defined control codes are in the range 128-255. We generally use
122 the standard Python value for the Linux signal and add 128. Example:
123
124 >>> signal.SIGUSR1
125 10
126 control_codes['graceful'] = 128 + 10
127 """
128
130 """For the given value, return its corresponding key."""
131 for key, val in self.iteritems():
132 if val is obj:
133 return key
134 raise ValueError("The given object could not be found: %r" % obj)
135
136 control_codes = _ControlCodes({'graceful': 138})
137
138
140 if command == 'stop':
141 win32serviceutil.StopService(service)
142 elif command == 'restart':
143 win32serviceutil.RestartService(service)
144 else:
145 win32serviceutil.ControlService(service, control_codes[command])
146
147
172
173
174 if __name__ == '__main__':
175 win32serviceutil.HandleCommandLine(PyWebService)
176