리눅스에서 Semaphore 사용시 주의점

최근 시스템에 문제가 있어서 디버깅을 하다가 디버거를 붙였다 나오면, 세마포어가 비정상 release 되는것처럼 보이는 희한한 버그를 발견했다.

조사해 보니 세마포어가 release되는게 아니라 sem_wait() 에서 EINTR을 받고 sem_wait() 가 -1을 리턴하는 문제였다.

일부 시그널 핸들러에 의해 이렇게 되는 경우가 있다고 하는데, 따라서 세마포어를 쓸때는 그냥 쓰지 말고 다음과 같이 wrapper 함수를 하나 만들어서 쓰는게 좋을것 같다.

void sema_wait_nointr(sem_t *sem)
{
   int sema_result;

   sema_result = sem_wait(sem);
   while ((sema_result == -1) && (errno == EINTR))
   {
      sema_result = sem_wait(sem);
   }
}


위 문제는 다음의 코드로 확인해 볼수 있다.

<sema_test.c>

#include <stdio.h>
#include <semaphore.h>

sem_t sema_block;

int main()
{
    sem_init(&sema_block, 0, 0);

    while (1)
    {
        int sem_result;
        sem_result = sem_wait(&sema_block);
        printf("Semaphore is released! : %d\n", sem_result);
        perror("Semaphore error! ");
    }
}

위 파일을 컴파일한후 실행 시켜보자.

$ gcc sema_test.c -l pthread
$ ./a.out &
[1] 15965
$ pstack 15965
#0  0x00b44402 in __kernel_vsyscall ()
#1  0x006f314e in sem_wait@GLIBC_2.0 () from /lib/libpthread.so.0
#2  0x0804847d in main ()
Semaphore is released! : -1
Semaphore error!: Interrupted system call


pstack 명령으로 허무하게 세마포어가 그냥 뚤려버리는것을 볼수가 있다.

혹시나 싶어 mutex 를 가지고 테스트 해보니 mutex 에서는 이런 문제가 발생하지 않는다.

* 3월 31일 추가
- 다른 child process 나 thread 에서 system() 과 같은 함수를 수행해도 (아마도 수행완료후 SIGCHLD 발행시?)
  똑같은 증상이 나타나는것을 확인했다.

이 글과 관련있는 글을 자동검색한 결과입니다 [?]

by 철이 | 2009/03/26 17:46 | 코드의 연금술사 | 트랙백 | 덧글(2)

트랙백 주소 : http://cityelf.egloos.com/tb/9370134
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by Lohengrin at 2009/03/27 13:21
이거 모르고 있다가 낭패 보는 경우가 많죠
Commented by 철이 at 2009/03/30 13:27
네. 제가 이번에 그런 경우를 당했네요. ^^a

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶