win32.py (4235B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\process\win32.py 2 import os 3 import win32api 4 import win32con 5 import win32event 6 import win32service 7 import win32serviceutil 8 from cherrypy.process import wspbus, plugins 9 10 class ConsoleCtrlHandler(plugins.SimplePlugin): 11 12 def __init__(self, bus): 13 self.is_set = False 14 plugins.SimplePlugin.__init__(self, bus) 15 16 def start(self): 17 if self.is_set: 18 self.bus.log('Handler for console events already set.', level=40) 19 return 20 result = win32api.SetConsoleCtrlHandler(self.handle, 1) 21 if result == 0: 22 self.bus.log('Could not SetConsoleCtrlHandler (error %r)' % win32api.GetLastError(), level=40) 23 else: 24 self.bus.log('Set handler for console events.', level=40) 25 self.is_set = True 26 27 def stop(self): 28 if not self.is_set: 29 self.bus.log('Handler for console events already off.', level=40) 30 return 31 try: 32 result = win32api.SetConsoleCtrlHandler(self.handle, 0) 33 except ValueError: 34 result = 1 35 36 if result == 0: 37 self.bus.log('Could not remove SetConsoleCtrlHandler (error %r)' % win32api.GetLastError(), level=40) 38 else: 39 self.bus.log('Removed handler for console events.', level=40) 40 self.is_set = False 41 42 def handle(self, event): 43 if event in (win32con.CTRL_C_EVENT, 44 win32con.CTRL_LOGOFF_EVENT, 45 win32con.CTRL_BREAK_EVENT, 46 win32con.CTRL_SHUTDOWN_EVENT, 47 win32con.CTRL_CLOSE_EVENT): 48 self.bus.log('Console event %s: shutting down bus' % event) 49 try: 50 self.stop() 51 except ValueError: 52 pass 53 54 self.bus.exit() 55 return 1 56 return 0 57 58 59 class Win32Bus(wspbus.Bus): 60 61 def __init__(self): 62 self.events = {} 63 wspbus.Bus.__init__(self) 64 65 def _get_state_event(self, state): 66 try: 67 return self.events[state] 68 except KeyError: 69 event = win32event.CreateEvent(None, 0, 0, 'WSPBus %s Event (pid=%r)' % (state.name, os.getpid())) 70 self.events[state] = event 71 return event 72 73 def _get_state(self): 74 return self._state 75 76 def _set_state(self, value): 77 self._state = value 78 event = self._get_state_event(value) 79 win32event.PulseEvent(event) 80 81 state = property(_get_state, _set_state) 82 83 def wait(self, state, interval = 0.1, channel = None): 84 if isinstance(state, (tuple, list)): 85 if self.state not in state: 86 events = tuple([ self._get_state_event(s) for s in state ]) 87 win32event.WaitForMultipleObjects(events, 0, win32event.INFINITE) 88 elif self.state != state: 89 event = self._get_state_event(state) 90 win32event.WaitForSingleObject(event, win32event.INFINITE) 91 92 93 class _ControlCodes(dict): 94 95 def key_for(self, obj): 96 for key, val in self.items(): 97 if val is obj: 98 return key 99 100 raise ValueError('The given object could not be found: %r' % obj) 101 102 103 control_codes = _ControlCodes({'graceful': 138}) 104 105 def signal_child(service, command): 106 if command == 'stop': 107 win32serviceutil.StopService(service) 108 elif command == 'restart': 109 win32serviceutil.RestartService(service) 110 else: 111 win32serviceutil.ControlService(service, control_codes[command]) 112 113 114 class PyWebService(win32serviceutil.ServiceFramework): 115 _svc_name_ = 'Python Web Service' 116 _svc_display_name_ = 'Python Web Service' 117 _svc_deps_ = None 118 _exe_name_ = 'pywebsvc' 119 _exe_args_ = None 120 _svc_description_ = 'Python Web Service' 121 122 def SvcDoRun(self): 123 from cherrypy import process 124 process.bus.start() 125 process.bus.block() 126 127 def SvcStop(self): 128 from cherrypy import process 129 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 130 process.bus.exit() 131 132 def SvcOther(self, control): 133 process.bus.publish(control_codes.key_for(control)) 134 135 136 if __name__ == '__main__': 137 win32serviceutil.HandleCommandLine(PyWebService)