thread에서 signal 받기.
글쓴이: whxoans / 작성시간: 수, 2009/02/04 - 10:39오후
BOSS & WORKER 모델에서
worker thread는 생성 detach되며 무한 루프를 돌며 시그널을 통해 작업을 기다립니다.
작업이 완료가 되면 main thread에게 작업이 끝났다는 의미의 SIGUSR2를 발신합니다.
...... sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmaksk, SIGUSR1); pthread_sigmask(SIG_BLOCK, &sigmask, NULL); while ( 1 ) { sigwait(SIGUSR1, signo); 자신의 상태(전역변수)를 BUSY로 변경. 원하는 작업 수행.... 자신의 상태(전역변수)를 WAIT로 변경. pthread_mutex_lock(&mutex); pthread_sigkill(main_thread, SIGUSR2); pthread_mutex_unlock(&mutex); }
main thread는 작업 요청을 받아 worker thread에게 SIGUSR1로 신호해 작업을 지시합니다.
모든 worker thread가 BUSY 상태일 경우 자신에게 SIGUSR2가 오길 기다립니다.
하지만 문제는 SIGUSR2이 pthread_sigmask에 의해 block이나 unblock이 되어 있지 않으면
핸들러가 없는 시그널로 프로그램이 종료 됩니다.
....... sigset_t sigmask; sigemptyset(&sigmask); sigaddset(&sigmaksk, SIGUSR2); signal(SIGUSR2, SIG_IGN) while ( 1 ) { 요청이 들어올 떄까지 block. 요청이 들어오면 필수 정보를 세팅한 후 상태가 WAIT인 thread를 찾은 후 존재하면 pthread_mutex_lock(&mutex); pthread_sigkill(worker_thread\[index\] , SIGUSR1); pthread_mutex_unlock(&mutex); 모든 쓰레드가 BUSY라면 signal(SIGUSR2, SIG_DFL); pthread_sigmask(SIG_BLOCK, &sigmask, NULL); signal(SIGUSR2, SIG_IGN) sigwait(SIGUSR2, signo); // <- 작업 종료 신호 대기 지점. 다시 WAIT인 thread를 찾아 작업 신호(SIGUSR1) 발신. }
원하는 타이밍에만 해당 시그널을 받는 법이 없을까요??
요는 무한 루프를 돌며 작업 요청을 하고 작업 요청을 받는 구조인데
작업을 요청한 쪽에서 자신이 쉬고 있는 thread가 없을때만 BUSY_WAIT를 피하기 위해
sigwait()로 블럭상태를 만들려 하는데 위 처럼 했을 경우는 SIGUSR2로 인해 종료가 되며
worker thread와 같은 형태로 시그널을 기다리니 시그널이 오지 않고 block되는 현상이 있습니다.
지금까지 고민하 바로는 제가 signal에 대한 이해가 떨어지는 것으로 예상하고 있습니다.
제가 놓치고 있는 부분이나 더 좋은 구조 혹은 유사한 경험 등이 있으시다면
조언 부탁드리겠습니다. :D
Forums:
자문자답.
또 자문자답이 됐네요. :)
가장 큰 문제는 메인 쓰레드가 아니라 SIGUSR2의 핸들러 혹은 시그널 마스킹이 안되어 있는 worker thread로 보내고 있었습니다;
사칙연산자 '+'를 '-' 오타를 낸 것이죠.
또, 알아낸 것은 시그널 마스크가 SIG_BLOCK 상태에서만 sigwait 수행 후 해당 시그널이 올때까지 기다릴 수 있다는 것입니다.
추가적인 문제로 현재 모든 쓰레드가 작업 중이라 sigusr2(작업이 완료 되었다는 신호)가 들어오기 전까지 accept를 할 수 없는
구조적인 문제에 봉착했네요;
번뜩 든 생각으로는 accept만을 수행하는 thread를 생성하여 que를 만들고 FIFO 꺼내서 쓰는 방식으로 해야 하지 않을까 합니다.
일반적으로 connection과 close가 매우 빈번한 server에서는 어떤 구조로 처리하고 있는지 궁금하네요.
worker thread 는
worker thread 는 pthread_cond_wait() 로 대기.
main thread 에 작업거리가 발생하면 queue 에 밀어넣고 pthread_cond_signal() 로 woker thread 를 깨운다.
필요하다면, worker thread 를 깨운 후 main thread 는 pthread_cond_wait() 로 대기
worker thread 는 작업을 마치고 pthread_cond_signal() 로 worker thread 를 깨운다.
실제로 사용한 적은 없지만, 이렇게하면 되지 않을까하는 생각에 두드렸던 코드가 있습니다.
http://kldp.org/node/101059#comment-469458
생각하시는대로, queue 를 사용한다면 work_done 을 main_thread 가 기다릴 필요는 없습니다.
queue 에 접근할 때 mutex 락을 걸어야 한다는 조건만 지켜주면 되겠죠.
OTL
댓글 달기