2010-07-12 6 views
13

Python 스크립트는 조기 종료를 막기 위해 프로세스 프로세스 모듈로 SIGINT 신호를 차단하지만이 신호는 Popen으로 여는 하위 프로세스로 전달됩니다. 사용자가 ctrl-c를 눌렀을 때 조기에 종료되지 않도록이 신호를 하위 프로세스로 전달하는 것을 방지 할 수있는 방법이 있습니까?SIGINT가 파이썬에서 서브 프로세스로 전달되는 것을 멈추는 방법은 무엇입니까?

+0

어떤 플랫폼을 사용하고 계십니까? – ChristopheD

+0

나는 우분투 리눅스에있어. – shino

답변

2

tty 모듈을 사용하여 ctrl-c의 역할을 다시 지정할 수 있습니다.이 모듈을 사용하면 신호 할당을 조작 할 수 있습니다. 그러나 프로그램을 수정하기 전의 상태로 되돌려 놓지 않으면 프로그램이 종료 된 후에도 쉘의 전체 세션을 지속하게됩니다.

다음은 이전 tty 설정을 저장하고 ctrl-c에 ctrl-c를 다시 할당 한 다음 종료시 이전 tty 설정을 복원하는 간단한 코드 스 니펫입니다. 당신이 하위 프로세스를 시작할 때 SIGINT (signal.signal(signal.SIGINT, signal.SIG_IGN)를) 무시하는 신호 모듈을 사용 그래서 만약

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) 
14

신호 처리기는 자동으로, 당신의 자식 프로세스를합니다 상속됩니다.

두 가지 중요한주의 사항이 있지만,이 있습니다

  • 당신은 당신이 있기 때문에,
  • 사용자 정의 시그널 핸들러가 기본 핸들러으로 재설정됩니다 자식 프로세스를 생성 전에 핸들러 를 무시 설정해야 자식 프로세스는 핸들러 코드를 실행하기 위해 핸들러 코드에 액세스 할 수 없습니다.

SIGINT를 무시하는 것보다 처리를 사용자 정의해야하는 경우, 하위 프로세스를 생성하는 동안 SIGINT를 일시적으로 무시한 다음 사용자 정의 신호 처리기를 (다시) 설정해야합니다.

SIGINT를 잡으려고하고 깃발을 설정하여 즉시 안전 포인트를 종료 할 수 있도록하려면 안전 포인트에 도달하면 코드가 수동으로 자손을 정리해야한다는 것을 기억하십시오. 자식 프로세스와 시작하는 프로세스는 SIGINT를 무시합니다.

+0

이것이 작동하는 경우 (항상 그렇지는 않음) 터미널을 사용하는 것보다 더 나은 옵션입니다. – zwol

+0

popen() 대신 fork()/exec()를 사용하면 exec() 전에 fork() 후에 SIG_IGN을 수행 할 수 있습니다. 이렇게하면 부모에서 처리기를 일시적으로 사용하지 않도록 할 수 있습니다. 당신이 무엇을 하든지 경쟁 조건이 될 것 같지만 fork()/exec() 방법은 조금 더 안전 해 보입니다. 물론, OP는 파이썬의 Popen에 대해 묻고 있었지만,이 질문은 Posix에 관한 것 같습니다. 그래서 내가 여기 왔어. – thejoshwolfe

+1

@thejoshwolfe : 경쟁 조건을 피하기 위해 sigprocmask()를 사용하여 신호를 지연시키고 핸들러를 설정하고 포크를 설정 한 다음 핸들러를 다시 설정 한 다음 sigprocmask를 다시 사용하여 신호를 다시 활성화합니다. (그리고 sigprocmask에 대한 호출 사이에 어떤 신호가 도착하면, 그들은이 시점에서 전달 될 것입니다.) –

관련 문제