2007년 7월 25일 수요일

fork와 thread 조합에서 만난 버그

개발 플랫폼 정보: AIX 5.3, xlc,oracle Pr*C

프로그램은 conf 파일을 읽고 패스워드를 입력받는다.
DB 접속 테스트. daemon으로 동작하기 위해 terminal 종속을 끝는다.
fork를 호출하여 Process M, A, W 로 분기한다.

M - Master Process
A - Admin Process
W - Work Process

W 프로세스는 다시 pthread_create 을 호출하여 thread R, I, M 로 분리된다.

r - recv thread
i - Issue thread
m - monitor thread

thread 생성후 pthread_key을 사용하여 hsm세션을 정보를 thread별로 만든다.
(thread specific data)

버그는 W 가 임의 동작으로 죽은후 M이 W을 다시 fork 한 후 W가 pthread_key 로
저장하는 세션 정보에서 발생한다. W 가 만드는 r, i, m 스레드가 자신들이 각자
만든 값으로 설정되는 것이 아니라(즉, 각 스레드가 최소 한번은 pthread_setspecific()
함수를 호출해야 하나 그렇지 못한다). pthread_setspecific()은 한번만 이루어지고
pthread_getspecific()이 3번 호출되면 2번째 호출부터는 NULL이 리턴되는 것이 아니다.
정상적인 시나리오는 getspecific() 호출에 NULL이 리턴되고 setspecific() 호출로 값을
설정한다.

버그가 발생한 이유는 M이 W을 초기화할 당시 hsm 을 완전히 지우지 않았다.
M이 fork로 생성한 W는 M의 hsm 정보를 가지고 있다(이 말은 hsm에 대한 pthread_key
을 가지고 있다는 것과 같다).

W의 1번째 hsm 정보는 M의 hsm정보를 가져오고 이후 pthread_create는 동일한 pthread_key
로부터 어떤 가비지 값을 가져오는 듯 하다.

--> fork(), pthread_create()의 혼합사용에서 있어서, pthread_key(), pthread_get,setspecific()
사용시 대단히 fork() 이전에 pthread_key_t은 삭제되어야 한다.