def interrupt_main_thread(main_thread): ''' Generates a KeyboardInterrupt in the main thread by sending a Ctrl+C or by calling thread.interrupt_main(). :param main_thread: Needed because Jython needs main_thread._thread.interrupt() to be called. Note: if unable to send a Ctrl+C, the KeyboardInterrupt will only be raised when the next Python instruction is about to be executed (so, it won't interrupt a sleep(1000)). ''' pydev_log.debug('Interrupt main thread.') called = False try: if os.name == 'posix': # On Linux we can't interrupt 0 as in Windows because it's # actually owned by a process -- on the good side, signals # work much better on Linux! os.kill(os.getpid(), signal.SIGINT) called = True elif os.name == 'nt': # This generates a Ctrl+C only for the current process and not # to the process group! # Note: there doesn't seem to be any public documentation for this # function (although it seems to be present from Windows Server 2003 SP1 onwards # according to: https://www.geoffchappell.com/studies/windows/win32/kernel32/api/index.htm) ctypes.windll.kernel32.CtrlRoutine(0) # The code below is deprecated because it actually sends a Ctrl+C # to the process group, so, if this was a process created without # passing `CREATE_NEW_PROCESS_GROUP` the signal may be sent to the # parent process and to sub-processes too (which is not ideal -- # for instance, when using pytest-xdist, it'll actually stop the # testing, even when called in the subprocess). # if hasattr_checked(signal, 'CTRL_C_EVENT'): # os.kill(0, signal.CTRL_C_EVENT) # else: # # Python 2.6 # ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, 0) called = True except: # If something went wrong, fallback to interrupting when the next # Python instruction is being called. pydev_log.exception('Error interrupting main thread (using fallback).') if not called: try: # In this case, we don't really interrupt a sleep() nor IO operations # (this makes the KeyboardInterrupt be sent only when the next Python # instruction is about to be executed). if hasattr(thread, 'interrupt_main'): thread.interrupt_main() else: main_thread._thread.interrupt() # Jython except: pydev_log.exception('Error on interrupt main thread fallback.')
def interrupt(self): self.buffer = None # Also clear the buffer when it's interrupted. try: if self.interruptable: called = False try: # Fix for #PyDev-500: Console interrupt can't interrupt on sleep import os import signal if os.name == 'posix': # On Linux we can't interrupt 0 as in Windows because it's # actually owned by a process -- on the good side, signals # work much better on Linux! os.kill(os.getpid(), signal.SIGINT) called = True elif os.name == 'nt': # Stupid windows: sending a Ctrl+C to a process given its pid # is absurdly difficult. # There are utilities to make it work such as # http://www.latenighthacking.com/projects/2003/sendSignal/ # but fortunately for us, it seems Python does allow a CTRL_C_EVENT # for the current process in Windows if pid 0 is passed... if we needed # to send a signal to another process the approach would be # much more difficult. # Still, note that CTRL_C_EVENT is only Python 2.7 onwards... # Also, this doesn't seem to be documented anywhere!? (stumbled # upon it by chance after digging quite a lot). os.kill(0, signal.CTRL_C_EVENT) called = True except: # Many things to go wrong (from CTRL_C_EVENT not being there # to failing import signal)... if that's the case, ask for # forgiveness and go on to the approach which will interrupt # the main thread (but it'll only work when it's executing some Python # code -- not on sleep() for instance). pass if not called: if hasattr(thread, 'interrupt_main'): # Jython doesn't have it thread.interrupt_main() else: self.mainThread._thread.interrupt() # Jython self.finish_exec(False) return True except: traceback.print_exc() return False