| 11 | | from cherrypy.restsrv import wspbus |
|---|
| | 11 | from cherrypy.restsrv 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 | 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()) |
|---|
| | 29 | else: |
|---|
| | 30 | self.is_set = True |
|---|
| | 31 | |
|---|
| | 32 | def stop(self): |
|---|
| | 33 | if not self.is_set: |
|---|
| | 34 | return |
|---|
| | 35 | |
|---|
| | 36 | try: |
|---|
| | 37 | result = win32api.SetConsoleCtrlHandler(self.handle, 0) |
|---|
| | 38 | except ValueError: |
|---|
| | 39 | # "ValueError: The object has not been registered" |
|---|
| | 40 | result = 1 |
|---|
| | 41 | |
|---|
| | 42 | if result == 0: |
|---|
| | 43 | self.bus.log('Could not remove SetConsoleCtrlHandler (error %r)' % |
|---|
| | 44 | win32api.GetLastError()) |
|---|
| | 45 | else: |
|---|
| | 46 | self.is_set = False |
|---|
| | 47 | |
|---|
| | 48 | def handle(self, event): |
|---|
| | 49 | """Handle console control events (like Ctrl-C).""" |
|---|
| | 50 | if event in (win32con.CTRL_C_EVENT, win32con.CTRL_LOGOFF_EVENT, |
|---|
| | 51 | win32con.CTRL_BREAK_EVENT, win32con.CTRL_SHUTDOWN_EVENT, |
|---|
| | 52 | win32con.CTRL_CLOSE_EVENT): |
|---|
| | 53 | self.bus.log('Console event %s: shutting down bus' % event) |
|---|
| | 54 | |
|---|
| | 55 | # Remove self immediately so repeated Ctrl-C doesn't re-call it. |
|---|
| | 56 | try: |
|---|
| | 57 | self.stop() |
|---|
| | 58 | except ValueError: |
|---|
| | 59 | pass |
|---|
| | 60 | |
|---|
| | 61 | self.bus.exit() |
|---|
| | 62 | # 'First to return True stops the calls' |
|---|
| | 63 | return 1 |
|---|
| | 64 | return 0 |
|---|
| 28 | | |
|---|
| 29 | | def _console_event(self, event): |
|---|
| 30 | | """The handler for console control events (like Ctrl-C).""" |
|---|
| 31 | | if event in (win32con.CTRL_C_EVENT, win32con.CTRL_LOGOFF_EVENT, |
|---|
| 32 | | win32con.CTRL_BREAK_EVENT, win32con.CTRL_SHUTDOWN_EVENT, |
|---|
| 33 | | win32con.CTRL_CLOSE_EVENT): |
|---|
| 34 | | self.log('Console event %s: shutting down bus' % event) |
|---|
| 35 | | |
|---|
| 36 | | # Remove this CtrlHandler so repeated Ctrl-C doesn't re-call it. |
|---|
| 37 | | try: |
|---|
| 38 | | result = win32api.SetConsoleCtrlHandler(self._console_event, 0) |
|---|
| 39 | | if result == 0: |
|---|
| 40 | | self.log('Could not remove SetConsoleCtrlHandler (error %r)' % |
|---|
| 41 | | win32api.GetLastError()) |
|---|
| 42 | | except ValueError: |
|---|
| 43 | | pass |
|---|
| 44 | | |
|---|
| 45 | | self.exit() |
|---|
| 46 | | # 'First to return True stops the calls' |
|---|
| 47 | | return 1 |
|---|
| 48 | | return 0 |
|---|