본문 바로가기
CS 지식/시스템 프로그래밍

[C언어] pthread 라이브러리를 이용해서 스레드에게 signal 보내기

by 코딩하는 동현 2025. 1. 28.

Sending a Signal to Thread

멀티 쓰레드 환경에서 시그널을 보내는 방법과 이를 다루는 코드 예제를 알아본다.


기본 환경

아래는 간단한 멀티 쓰레드 환경을 구현한 코드이다.
세 개의 쓰레드가 각각 thread1, thread2, thread3 함수를 실행하며, 각 함수는 무한 루프 내에서 메시지를 출력한다.

 
void* thread1(void *data){
    while(1){
        printf("thread 1\n");
        sleep(2);
    }
}
void* thread2(void *data){
    while(1){
        printf("thread 2\n");
        sleep(2);
    }
}
void* thread3(void *data){
    while(1){
        printf("thread 3\n");
        sleep(2);
    }
}

메인 쓰레드가 종료될 때의 동작

메인 쓰레드가 종료되면 나머지 쓰레드 역시 종료된다. kill()을 이용해 SIGTERM 시그널을 보내는 예제는 다음과 같다.

int main(){
    pthread_t tid[3];
    int thr_ret;   
    thr_ret = pthread_create(&tid[0], NULL, thread1, NULL);
    thr_ret = pthread_create(&tid[1], NULL, thread2, NULL);
    thr_ret = pthread_create(&tid[2], NULL, thread3, NULL);
    sleep(3);
    kill(getpid(), SIGTERM);
    printf("Main return\n");
    return 0;
}

 

결과:

  • 메인 쓰레드가 SIGTERM을 받고 종료되며, 모든 쓰레드가 함께 종료된다.

메인 쓰레드에서 시그널 핸들러 실행

시그널 핸들러는 기본적으로 메인 쓰레드에서만 실행된다. 다음은 SIGALRM 시그널을 처리하는 핸들러를 등록한 코드이다.

void sig_handler(int signo) {
    printf("Signal %d handled in main thread\n", signo);
}

int main() {
    pthread_t tid[3];
    int thr_ret;

    signal(SIGALRM, sig_handler);  // 시그널 핸들러 등록

    thr_ret = pthread_create(&tid[0], NULL, thread1, NULL);
    thr_ret = pthread_create(&tid[1], NULL, thread2, NULL);
    thr_ret = pthread_create(&tid[2], NULL, thread3, NULL);

    sleep(3);
    kill(getpid(), SIGALRM);  // SIGALRM 시그널 전송

    printf("Main return\n");
    return 0;
}

 

결과:

  • SIGALRM 시그널을 처리하는 핸들러가 호출되며, 이는 메인 쓰레드에서 실행된다.

특정 쓰레드에 시그널 보내기

pthread_kill() 함수는 특정 쓰레드 ID에 시그널을 보낼 수 있다. 하지만 SIGTERM 또는 SIGKILL은 모든 쓰레드를 종료시킨다는 점에 유의해야 한다.

int main() {
    pthread_t tid[3];
    int thr_ret;

    signal(SIGALRM, sig_handler);  // 시그널 핸들러 등록

    thr_ret = pthread_create(&tid[0], NULL, thread1, NULL);
    thr_ret = pthread_create(&tid[1], NULL, thread2, NULL);
    thr_ret = pthread_create(&tid[2], NULL, thread3, NULL);

    sleep(3);

    pthread_kill(tid[0], SIGALRM);  // 특정 쓰레드(tid[0])에 SIGALRM 전송
    // pthread_kill(tid[1], SIGALRM);
    // pthread_kill(tid[2], SIGALRM);

    sleep(10);
    printf("Main return\n");
    return 0;
}
 

결과:

  • pthread_kill()로 지정된 쓰레드에 시그널을 전달한다.
  • 전달된 시그널은 해당 쓰레드의 시그널 핸들러에서 처리된다.

추가 설명

  1. 시그널 핸들링 동작
    • POSIX 표준에 따르면, 시그널은 특정 쓰레드에 직접 전달되거나, 해당 쓰레드가 시그널 핸들러를 실행하게 된다.
    • SIGTERM과 SIGKILL은 프로세스 전체를 대상으로 하므로 모든 쓰레드를 종료시킨다.
  2. pthread_kill()와 kill() 차이
    • kill()은 프로세스 전체에 시그널을 보낸다.
    • pthread_kill()은 특정 쓰레드에 시그널을 전달할 수 있다.
반응형

댓글