2012-10-18 1 views
12

내 멀티 스레드 GUI 응용 프로그램에서 다음 신호 처리 코드가 있습니다. 나는 그것이 안전 올바른 및 스레딩 될 수 있도록이 코드를 향상시키고 자하지만, 신호 처리에 내가 완전히 이해하지 않는 몇 가지가 있습니다 :다중 스레드 환경에서 신호 처리기 기능

  • 신호 내가 스레드를 가질 수 있습니다 (프로세스 또는 스레드 수준에서 처리됩니다 특정 신호 처리기)?
  • 여기서 스레드 컨텍스트는 signal_handler 함수가 실행됩니까?
  • 짧은 시간에 많은 SIGTERM 신호를 보낼 수 있습니까?
  • signal_handler의 병렬 실행을 방지하기 위해 뮤텍스를 사용하는 것이 합리적입니까?
    void signal_handler(int sig) 
    { 
         switch (sig) 
         { 
         case SIGTERM: 
          ::wxLogMessage(wxT("SIGTERM signal received ...")); 
          break; 
         case SIGINT: 
          ::wxLogMessage(wxT("SIGINT signal received ...")); 
          break; 
         case SIGUSR1: 
          ::wxLogMessage(wxT("SIGUSR1 signal received ...")); 
          break; 
         default: 
          ::wxLogMessage(wxT("Unknown signal received ...")); 
         } 
    
         // send wxCloseEvent to main application window 
         ::wxGetApp().GetTopWindow()->Close(true); 
    } 
    


나는 나의 init 함수에 신호 핸들러를 등록 :

// register signal handlers 
signal(SIGTERM, signal_handler); 
signal(SIGINT, signal_handler); 
signal(SIGUSR1, signal_handler); 

답변

10

매우 조심하십시오 signal(7) 페이지는 매우 몇 가지 기능을합니다 ("비동기 신호를 말하고으로 -safe " ones)는 (직접 또는 간접적으로) 내부 시그널 핸들러로 불릴 수 있습니다. 뮤텍스 관련 함수는 아마도 시그널 핸들러에서 호출되어서는 안됩니다. 또한 pthreads(7)

신호 처리기에서 volatile sigatomic_t 변수를 설정하고 해당 플래그의 값을 수시로 테스트하는 것이 좋습니다. C++ 11 (또는 C11) 원자가있는 경우 (예 : C++ 11 std::atomic 또는 C11 <stdatomic.h> 일 경우, 그 의미에서 volatile 변수도 원자 적으로 만들 수 있습니다. 그런 다음 원자 하중 시설을 사용하여 테스트하십시오.

쿼트 문서는 following trick 제안 : 시작시 자동으로 pipe(2)을 만든 후 신호 처리기 write(2) 하나 (또는 ​​그 이상)의 바이트 [S]으로합니다 (write 콜이 신호 안전 비동기로서 지정됨)이 동일한 프로세스에 파이프를 연결하고 GUI 이벤트 루프를 해당 파이프의 읽기 끝 poll(2)으로하십시오. Qt를 가진 신호를 처리 할 수 ​​

리눅스 고유의 방법은 QSocketNotifier와 아마 signalfd(2)을 사용할 수 있습니다 (이름에도 불구하고, 그것은 CF- 폴 가능 파일 기술자에서 작동하지 소켓). 다른 GUI 도구 키트를 사용하면 폴링 할 파일 설명자 (signalfd 또는 pipe의 파일 설명자)를 추가 할 수도 있습니다.

+2

신호 처리기에서 std :: atomic을 사용한다고해서 lock-free 구현이 보장되는 것은 아닙니다. 참조하십시오 : http://www.informit.com/articles/article.aspx?p=2204014 – Corvusoft

4

이 답변은 POSIX 스레드 (pthreads)를 나타냅니다. (1)를 참조하면

:

신호는 스레드 수준에서 처리 할 수 ​​ , 예. 프로세스의 두 개 이상의 스레드가 신호를 처리하고 신호가 프로세스로 보내지지만 특정 스레드로 보내지면 어떤 스레드의 처리기가 신호를 처리할지 결정되지 않습니다.

신호 처리기를 설정 스레드 컨텍스트에 excuted한다 :

2를 참조하여 (자세한 내용 man pthread_kill() 참조). 여기에는 주 스레드가 포함됩니다.동일한 유형의 하나 개 이상의 신호들은 상기 신호 큐를 떠나기 전에 오직 하나의 신호로 응축 될 수있는 동일한 방법으로 전송 된 경우

3을 참조

. 이것이 내가 확실히 알지 못하는 쓰레드 레벨과 구별 될 수 있는지, 나는 인정해야한다. 공유 자원이 게임에 참여하는 경우

: 예, 적어도 동시에 이러한 리소스에 액세스하는 핸들러 '코드의 부분 4를 참조하면

. 그리고 이것은 또한 구현하려고하는 논리에 달려 있습니다.

17
  • 신호 처리기는 프로세스 당 상태입니다. 즉, 프로세스의 모든 스레드는 동일한 신호 처리기 기능 세트를 공유합니다.
  • 신호 마스크는 스레드 별 상태입니다. 신호는 스레드별로 차단하거나 차단 해제 할 수 있습니다.
  • 신호는 프로세스 또는 스레드 지향 일 수 있습니다. 신호가 프로세스 지향이면, 현재 신호 유형이 차단되지 않은 임의의 스레드가 처리하도록 선택됩니다.

멀티 스레드 응용 프로그램에서 신호를 처리하는 간단한 방법은 전용 신호 처리 스레드로 하나의 스레드를 만드는 것입니다. 관심있는 모든 신호는 모든 스레드에서 차단됩니다. 신호 처리기가 설정되지 않았습니다. 신호 처리 스레드는 루프에서 sigwaitinfo()을 호출하여 수신 된 신호에 대해 작동합니다.

는 신호가 신호 처리기에서 처리되지 않기 때문에 당신이, 당신이 호출 할 기능 비동기 시그널에 안전인지 여부에 대해 걱정할 필요가 없습니다 것을 의미합니다 - 그들은에 의해 동 기적으로 처리하고 당신의 전용 신호 처리 스레드는 좋아하는 함수를 호출 할 수 있습니다 (예를 들어, 일반 스레드 동기화 함수를 사용하여 다른 스레드를 깨울 수 있습니다).