signals.py 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. import logging
  2. import os
  3. import signal
  4. import sys
  5. logger = logging.getLogger(__name__)
  6. EXIT_CODE_FROM_SIGNAL = 128
  7. def handle_signal(signal_number, frame):
  8. '''
  9. Send the signal to all processes in borgmatic's process group, which includes child processes.
  10. '''
  11. # Prevent infinite signal handler recursion. If the parent frame is this very same handler
  12. # function, we know we're recursing.
  13. if frame.f_back.f_code.co_name == handle_signal.__name__:
  14. return
  15. os.killpg(os.getpgrp(), signal_number)
  16. if signal_number == signal.SIGTERM:
  17. logger.critical('Exiting due to TERM signal')
  18. sys.exit(EXIT_CODE_FROM_SIGNAL + signal.SIGTERM)
  19. elif signal_number == signal.SIGINT:
  20. # Borg doesn't always exit on a SIGINT, so give it a little encouragement.
  21. os.killpg(os.getpgrp(), signal.SIGTERM)
  22. raise KeyboardInterrupt()
  23. def configure_signals():
  24. '''
  25. Configure borgmatic's signal handlers to pass relevant signals through to any child processes
  26. like Borg.
  27. '''
  28. for signal_number in (
  29. signal.SIGHUP,
  30. signal.SIGINT,
  31. signal.SIGTERM,
  32. signal.SIGUSR1,
  33. signal.SIGUSR2,
  34. ):
  35. signal.signal(signal_number, handle_signal)