2014-12-06 3 views
0

사용자가 인터럽트 (예 : CTRL + C)를 보내고 output_report() 메서드가 실행될 때까지 영원히 실행되는 멀티 스레드 응용 프로그램을 만듭니다. 다음 코드 샘플은 다음과 같습니다pthread 조건이 만족스럽지 않다

void output_report(int signo) { 
    printf("Exiting!\n"); 

    pthread_mutex_lock(&mutex_num_of_threads); 
    programClosing = true; 
    while (numOfThreads != 0){ 
     pthread_cond_wait(&allThreadsCompleteCond, &mutex_num_of_threads); 
    } 
    pthread_mutex_unlock(&mutex_num_of_threads); 

    printf("Closing Now!\n"); //This part is not reached 

    pthread_exit(NULL); // Is this needed? 
    exit(0); 
} 

void dispatch(struct pcap_pkthdr *header, const unsigned char *packet, 
     int verbose) { 

    static bool thread_settings_initialised = false; 

    //Only run the first time dispatch method runs 
    if (thread_settings_initialised == false){ 
     thread_settings_initialised = true; 

     if (signal(SIGINT, output_report) == SIG_ERR) 
      fprintf(stderr, "\ncan't catch SIGINT\n"); 

     //...  

     //Set mutex for the appropriate variables to remain thread safe 
     pthread_mutex_init(&mutex_num_of_threads, NULL); 
     //... 

     //Set attr so threads are "Detached" 
     pthread_attr_init(&attr); 
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 

     //Set pthread_cond_init 
     pthread_cond_init(&allThreadsCompleteCond, NULL); 
    } 

    //... 

    pthread_mutex_lock(&mutex_num_of_threads); 
    numOfThreads++; 
    pthread_mutex_unlock(&mutex_num_of_threads); 


    //... 
    int rc = pthread_create(&tid, &attr, analyse, (void *) &data); 
    //... 
} 

void analyse(void *thread_data) { 
    //... 

    pthread_mutex_lock(&mutex_num_of_threads); 
    numOfThreads--; 
    if (programClosing == true && numOfThreads == 0) { 
     pthread_cond_signal(&allThreadsCompleteCond); 
    } 
    pthread_mutex_unlock(&mutex_num_of_threads); 

    pthread_exit(NULL); 
} 

내 문제는 내가 CTRL + C를 사용하여 어느 때, 프로그램은 단지 종류의 프로그램이 계속 실행되고 내가 Ctrl 키를 사용해야합니다 (완전하게 종료를 중단한다는 것입니다. + z를 눌러 빠져 나옵니다.) 프로그램은 "Exiting"을 출력하지만 "지금 닫기"는 "allThreadsCompleteCond"가 충족되지 않는다는 의미는 아니지만 그 이유는 모르겠습니다.

UPDATE

덕분에 폴 그리피스의 대답에 나는 그렇게처럼 내 코드를 업데이트 :

void exitHandler(int signum){ 
    programClosing = 1; 
} 

void output_report(int signo) { 
    while (programClosing == 1){ 
     printf("Exiting!\n"); 
     //rest same as before 
     exit(0) 
    } 
} 

void dispatch(struct pcap_pkthdr *header, const unsigned char *packet, 
     int verbose) { 

    static bool thread_settings_initialised = false; 
    int rc; 

    printf("DISPATCH!\n"); 
    //Only run the first time dispatch method runs 
    if (thread_settings_initialised == false){ 
     thread_settings_initialised = true; 

     //Set mutex for the appropriate variables to remain thread safe 
     //.. 

     //Set attr so threads are "Detached" 
     //.. 

     //... 

     if (signal(SIGINT, exitHandler) == SIG_ERR) 
      fprintf(stderr, "\ncan't catch SIGINT\n"); 

     pthread_t exit_tid; 
     rc = pthread_create(&exit_tid, &attr, output_report, (void *) NULL); 
     if (rc) { 
      printf("ERROR; return code from pthread_create() is %d\n", rc); 
      exit(-1); 
     } 

    } 

    //... 
    ///same as before 

} 

이제 업데이트 된 코드는 여전히 않아도 출력되지 텍스트 "종료"!

+1

'의 printf()를''에 pthread_mutex_lock()''는 pthread_cond_wait() '및'pthread_mutex_unlock을() '신호 처리기에서 호출하는 것이 안전하지 않다. 당신이 보는 행동은 그 증거입니다. 전략을 재고해야합니다. –

+0

대체 뭐하는거야 –

+1

아마도 신호 처리기가 아무것도하지 않고'sig_atomic_t' 유형의 상태 변수를 설정하고 주기적으로 단일 스레드에서이를 확인하고 다른 스레드가 변경된 경우이를 닫습니다. 일반적으로 스레드와 신호를 혼합하면 이와 같은 많은 문제가 발생합니다. –

답변

1

printf() 특히, 여기서 pthread_mutex_lock(), pthread_cond_wait()pthread_mutex_unlock()은 신호 처리기에서 일반적으로 호출 할 수 없습니다. 당신이 보는 행동은 그 증거입니다. 때로는 그렇게 할 수는 있지만, 프로그램의 나머지 부분이 그렇게함으로써 악영향을받을 수 없다는 것을 확인하는 것이 포함됩니다. 평범하지 않은 프로그램의 경우 보통 가능하지 않습니다.

신호 처리는 시작하기에 충분히 까다로울 수 있으며 일반적으로 스레드와 신호를 혼합하면 작업이 훨씬 까다로워집니다. 일반적인 접근법은 (1) 신호 처리기에서 비동기 신호 안전성을 갖는 함수 만 호출하는 것입니다 (해당 연산자의 목록은 here입니다). 그리고 (2) 가능하면 신호 처리기에서 거의 작업을하지 마십시오. 또한 핸들러가 해당 조작에 역효과를 줄 수있는 신호에 의해 작업 세트가 중단되기를 원치 않는 (3) 신호 전달 또는 중요 섹션에 대한 일부 신호 차단에 대해 종종 생각할 필요가 있습니다.

volatile sig_atomic_t 유형의 변수는 신호 처리기에서 안전하게 쓸 수 있으므로 일반적인 전략은 신호 처리기에서 아무것도하지 않고 변수를 설정하여 주 프로그램이 주기적으로 검사하도록하는 것입니다. 예를 들어 :

volatile sig_atomic_t im_done = 0; 

void handler(int signum) 
{ 
    im_done = 1; 
} 

int main(void) 
{ 
    /* Do init stuff and register your signal handler */ 

    while (!im_done) { 

     /* Do your main work here */ 

    } 

    /* Clean up and get ready to exit here */ 

    return 0; 
} 
+0

새로운 코드는 어디에서나'output_report()'를 호출하지 않는 것 같아서 분명히'printf ("Exiting! \ n");의 효과를 볼 수 없으며'output_report()'자체는 여전히 쓰여진 것처럼 보입니다 당신이 원하는 것이 아닌 신호 처리기입니다. –

+0

죄송합니다. 잘못 쓰지만 동일한 결과입니다. 그것은 여전히 ​​작동하지 않습니다!.\t \t printf ("종료! \ n"); 도망 가지 마! –

+0

좋아, 그럼 앉아서 생각하고, 기본적으로 프로그램을 디자인하고 디버깅해야 할 것이다. 여기에 작은 스 니펫을 게시하고 작동하지 않는다고 말하면 작동을 시작하지 않을 것입니다. –

관련 문제