1 alarm(TIMEOUT);
2 pause();
3 alarm(0);
..

위와 같이 alarm()을 사용해서 TIMEOUT을 구현하는 경우 race condition 문제가 발생할 가능성이 있다. 1번에서 알람이 설정되고 2번이 실행되기 전에 프로세스 스케줄링이 변경되서 다른 프로세스가 실행되는 경우(서버가 과부하인 상태이고 TIMEOUT이 짧을때), 2번이 실행되기 전에 alarm이 만료되어서 signal을 받을수 있다. 그렇게되면 pause()는 무한정 블럭되어버린다.

이 문제를 해결하는 방법은 몇가지가 있는데 내가 자주 사용하는 방법은 sigsetjmp/siglongjmp를 사용하는 방법이다.

/* SIGALARM handler */
void
sigalrm_handler(int signo)
{
     siglongjmp(jmpbuf, 1);
}

int
main(void)
{
...

       /* SIGALRM에서 사용할 시그널 점프 등록 */
       if(sigsetjmp(jmpbuf, 1) != 0) {
           goto timeout;
       }

       /* 알람 설정 후 신호대기 */
       alarm(TIMEOUT);
       pause();

timeout:
       alarm(0);

...
}

위 코드에서는 SIGALRM이 발생하면 시그널 핸들러를 실행하고 sigsetjmp 위치로 점프한다. 그리고 다시 timeout으로 goto하기 때문에 race condition 상황이 발생해도 pause()는 실행되지 않는다.

'Linux > C/C++' 카테고리의 다른 글

mysql 프로시저  (0) 2012.11.07
Thread와 Signal  (0) 2012.10.19
log file format 조건  (0) 2012.10.19
전처리기 #define do{ 문장1; 문장2; 문장3 }while(0) 사용...  (0) 2012.09.24
UCDParser result to analysis a indexing content  (0) 2012.08.29