Package cherrypy :: Package process :: Module win32
[hide private]
[frames] | no frames]

Source Code for Module cherrypy.process.win32

  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   
14 -class ConsoleCtrlHandler(plugins.SimplePlugin):
15 """A WSPBus plugin for handling Win32 console events (like Ctrl-C).""" 16
17 - def __init__(self, bus):
18 self.is_set = False 19 plugins.SimplePlugin.__init__(self, bus)
20
21 - def start(self):
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
34 - def stop(self):
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 # "ValueError: The object has not been registered" 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
52 - def handle(self, event):
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 # Remove self immediately so repeated Ctrl-C doesn't re-call it. 60 try: 61 self.stop() 62 except ValueError: 63 pass 64 65 self.bus.exit() 66 # 'First to return True stops the calls' 67 return 1 68 return 0
69 70
71 -class Win32Bus(wspbus.Bus):
72 """A Web Site Process Bus implementation for Win32. 73 74 Instead of time.sleep, this bus blocks using native win32event objects. 75 """ 76
77 - def __init__(self):
78 self.events = {} 79 wspbus.Bus.__init__(self)
80
81 - def _get_state_event(self, state):
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
92 - def _get_state(self):
93 return self._state
94 - def _set_state(self, value):
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 # Don't wait for an event that beat us to the punch ;) 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 # Don't wait for an event that beat us to the punch ;) 113 if self.state != state: 114 event = self._get_state_event(state) 115 win32event.WaitForSingleObject(event, win32event.INFINITE)
116 117
118 -class _ControlCodes(dict):
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
129 - def key_for(self, obj):
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
139 -def signal_child(service, command):
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
148 -class PyWebService(win32serviceutil.ServiceFramework):
149 """Python Web Service.""" 150 151 _svc_name_ = "Python Web Service" 152 _svc_display_name_ = "Python Web Service" 153 _svc_deps_ = None # sequence of service names on which this depends 154 _exe_name_ = "pywebsvc" 155 _exe_args_ = None # Default to no arguments 156 157 # Only exists on Windows 2000 or later, ignored on windows NT 158 _svc_description_ = "Python Web Service" 159
160 - def SvcDoRun(self):
161 from cherrypy import process 162 process.bus.start() 163 process.bus.block()
164
165 - def SvcStop(self):
166 from cherrypy import process 167 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 168 process.bus.exit()
169
170 - def SvcOther(self, control):
172 173 174 if __name__ == '__main__': 175 win32serviceutil.HandleCommandLine(PyWebService) 176