Как остановить передачу SIGINT в подпроцесс в python? - PullRequest
13 голосов
/ 13 июля 2010

Мой скрипт python перехватывает сигнал SIGINT с модулем сигнала process , чтобы предотвратить преждевременный выход, но этот сигнал передается подпроцессу, который я открываю с помощью Popen.Есть ли способ предотвратить передачу этого сигнала в подпроцесс, чтобы он также не выходил преждевременно, когда пользователь нажимает Ctrl-C?

Ответы [ 2 ]

15 голосов
/ 17 сентября 2010

Обработчики сигналов наследуются при запуске подпроцесса, поэтому, если вы используете сигнальный модуль для игнорирования SIGINT (signal.signal(signal.SIGINT, signal.SIG_IGN)), то ваш дочерний процесс автоматически также будет.

Есть два важных предостережения:

  • Вы должны установить обработчик игнорирования до того, как вызовет дочерний процесс
  • Пользовательские обработчики сигналов сбрасываются на обработчики по умолчанию, поскольку дочерний процесс не будет иметь доступа к коду обработчика для его запуска.

Так что, если вам нужно настроить обработку SIGINT, а не просто игнорировать ее, вы, вероятно, захотите временно игнорировать SIGINT при порождении дочернего процесса, а затем (пере) установить свой собственный обработчик сигналов.

Если вы пытаетесь поймать SIGINT и установить флаг, чтобы вы могли выйти в безопасной точке, а не сразу, помните, что когда вы доберетесь до этой безопасной точки, ваш код должен будет вручную очистить своих потомков, так как ваш ребенок процесс и любые процессы, которые он запускает, будут игнорировать SIGINT.

2 голосов
/ 13 июля 2010

Вы можете переназначить роль ctrl-c, используя модуль tty, который позволяет манипулировать назначением сигналов. Тем не менее, имейте в виду, что если вы не вернете их такими, какими они были до изменения, они будут сохраняться в течение всего сеанса оболочки даже после выхода из программы.

Вот простой фрагмент кода, который поможет вам начать работу с сохранением старых настроек tty, переназначением ctrl-c на ctrl-x, а затем восстановлением предыдущих настроек tty при выходе.

import sys
import tty

# Back up previous tty settings
stdin_fileno = sys.stdin.fileno()
old_ttyattr = tty.tcgetattr(stdin_fileno)

try:
    print 'Reassigning ctrl-c to ctrl-x'

    # Enter raw mode on local tty
    tty.setraw(stdin_fileno)
    raw_ta = tty.tcgetattr(stdin_fileno)
    raw_ta[tty.LFLAG] |= tty.ISIG
    raw_ta[tty.OFLAG] |= tty.OPOST | tty.ONLCR

    # ^X is the new ^C, set this to 0 to disable it entirely
    raw_ta[tty.CC][tty.VINTR] = '\x18'  

    # Set raw tty as active tty
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, raw_ta)

    # Dummy program loop
    import time
    for _ in range(5):
        print 'doing stuff'
        time.sleep(1)

finally:
    print 'Resetting ctrl-c'
    # Restore previous tty no matter what
    tty.tcsetattr(stdin_fileno, tty.TCSANOW, old_ttyattr)
...