Search code examples
pythonlinuxsignalsposix

Catching signals other than SIGINT in Python


I'm writing an interactive Python CLI tool. I'd like to have the tool go into a "special text entry mode" when a specific signal is raised. I currently handle SIGINT properly and gracefully exit.

Questions:

  1. What signal should I use to enter this mode? (Something that doesn't get in the way of other functionality)
  2. What is the best way to catch this signal?
  3. How is this signal triggered in POSIX systems? Is it different in Windows?

Solution

  • POSIX specifies exactly two user defined signals:

    SIGUSR1 = 30
    SIGUSR2 = 31
    

    These two signals aren't triggered by any action, meaning you can explicitly define handlers for these and raise these signals for your purpose.

    import signal
    
    def handler(signum):
       if signum == signal.SIGUSR1:
           print('user defined interrupt!')
    
    signal.signal(signal.SIGUSR1, handler)
    

    These signals have been provided explicitly for the user's purpose, so it would be a good idea to raise and handle these signals in your application.


    To explicitly raise this signal with code, you would have to use:

    import os
    os.kill(os.getpid(), signal.SIGUSR1)
    

    Where os.getpid() returns the process ID of the current process. Replace this with the ID of the process you wish to kill (if it isn't the current one).

    Also, I should mention that SIGUSR1/2 are not supported in Windows. The documentation mentions that besides SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM, no other signal can be raised. A ValueError will be raised in any other case.