interrupt.py 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637
  1. """Utility to send an interrupt (Ctrl+C) signal to the main thread.
  2. This is necessary because Windows and POSIX use different models for Ctrl+C
  3. interrupts.
  4. """
  5. import platform
  6. import signal
  7. import threading
  8. def interrupt_main():
  9. """Interrupt the main Python thread with a SIGINT signal.
  10. In POSIX, signal.pthread_kill() is the most reliable way to send a signal
  11. to the main thread.
  12. os.kill() is often recommended, but it isn't guaranteed to deliver the
  13. signal to the main OS thread. Likewise, signal.raise_signal() delivers
  14. the signal to the current thread in POSIX. The issue is that if any other
  15. thread receives the signal, Python will set an internal flag and process it
  16. on the main thread at the next opportunity. If the main thread is executing
  17. C code or is blocked on a syscall (e.g. time.sleep(999999)) the signal
  18. handler won't execute until that's done---i.e. Python won't preempt the OS
  19. thread on its own.
  20. On Windows, pthread_kill is not available and os.kill() ignores its
  21. second argument and always kills the process. However,
  22. signal.raise_signal() does the right thing.
  23. """
  24. if platform.system() == "Windows":
  25. signal.raise_signal(signal.SIGINT)
  26. else:
  27. signal.pthread_kill(
  28. threading.main_thread().ident,
  29. signal.SIGINT,
  30. )