노무현 대통령 배너


2006. 6. 2. 14:05

Thread 취소와 종료

JOINC.co.kr

Thread 취소와 종료

Date: 2004/02/15

Topic: 시스템 프로그램

윤상배: dreamyun@yahoo.co.kr

1절. 소개

쓰레드에 대해서 학습을 해본 적이 있다면 Thread 취소와 종료에 대한 내용은 뻔한 것 아니냐라고 생각할 수 있을 것이다. 하지만 이 문서를 읽어 보면 왜 별도의 문서를 만들어서 종료와 취소에 대해서 다루었는지 이해하게 될 것이다.

2절. Thread 취소(cancellation)와 종료

쓰레드는 제어 가능한 객체로 필요에 따라 생성시킬 수 있듯이 필요에 따라서 중단시킬 수도 있다. 이 쓰레드 중단이라는 것이 매우 단순한 행위라고 생각되지만 생각처럼 그렇게 단순한 행위가 아니다. 멀티 쓰레드 프로그램이라면 쓰레드 간 동기화를 위해서 조건 변수 뮤텍스 등을 사용하고 있을 것이며, 여러 가지 공유 자원들 역시 가지고 있을 것이다.

몇 명의 인원이 같이 참가해서 진행하는 프로젝트가 있다고 생각해 보자. 그 중 한 명이 프로젝트에서 빠지면 나머지 인원이 프로젝트를 진행하는데 문제가 생기지 않도록 이런 저런 뒷 수습을 해주는 게 매우 중요하다. 쓰레드 역시 마찬가지로 중단(종료)시 뒷 수습을 해주는 것은 매우 중요한 일이다. 이 문서는 쓰레드 취소에 관련된 내용과 쓰레드 종료시 신경써야 될 (자원 정리와 같은) 것들에 대해서 알아보도록 한다.

2.1절. Thread 취소

멀티 쓰레드 프로그램에서 특정 쓰레드를 중단시키고자 할 때를 위해서 Pthread는 ptread_cancel()이라는 함수를 제공한다.

int pthread_cancel(pthread_t thread);

이 함수는 인자로 주어진 쓰레드 식별 번호 thread를 가지는 쓰레드를 중지시킨다. 명확히 말하자면 쓰레드를 중지시키는 게 아니고 쓰레드에 취소 요청을 하는 것으로 봐야 한다. 취소 요청을 받은 쓰레드가 어떻게 반응 할런지는 요청을 받은 쓰레드의 취소 상태 설정에 의존한다. 취소 요청을 받은 쓰레드는 취소 상태에 의해서 필요한 작업을 한 후 종료하게 된다. 취소 요청을 받아서 종료하는 쓰레드는 pthread_exit(PTHREAD_CANCELED)를 호출하고 종료한다.

pthread_cancel()에 의해서 취소가 통보된 쓰레드는 쓰레드 취소 상태의 설정에 따라서 취소 요청을 무시할 수도 취소 지점(cancellation point)까지 수행한 뒤에 종료 될 수도 있기 때문이다.

쓰레드 취소와 종료는 엄연히 다르다는 것을 이해하기 바란다. 그렇지 않으면 앞으로 문서의 내용을 읽는데 헛 갈릴 수 있다.

2.1.1절. 쓰레드 취소 상태의 설정

쓰레드가 pthread_cancel()에 의해서 취소 요청을 받았을 때 어떻게 반응할런 지를 결정하는 쓰레드 취소 상태는 여러 가지 방법에 의해서 결정된다. 취소 상태는 pthread_setcancelstat()에 의해 결정한다.

int pthread_setcancelstate(int state, int *oldstate);

첫 번째 인자인 state는 새로운 취소 상태를 설정하기 위해서 사용된다. 두 번째 인자인 oldstate는 이전의 취소 상태의 설정 값을 받아오기 위해서 사용된다. 이 함수는 다음과 같이 사용할 수 있다.

int old_cancel_state;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancel_state);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state);

만약 이전의 취소 상태 설정 값이 필요 없다면 old_cancel_state 대신 NULL을 사용하면 된다. 위의 사용에서 처럼 쓰레드는 PTHREAD_CANCEL_DISABLEPTHREAD_CANCEL_ENABLE 둘 중 하나의 취소 상태를 가질 수 있다.

만약 PTHREAD_CANCEL_ENABLE 상태라면 쓰레드는 취소 요청을 받아들이고 취소 지점까지 진행한 다음 취소 지점을 벗어나야지 종료한다. ENABLE 상태일 경우 별도로 취소 지점까지 진행한 다음 종료할 것인지 아니면 바로 종료할 것인지를 pthread_setcanceltype()를 통해 지정할 수 있다. 만약 PTHREAD_CANCEL_DISABLE 상태라면 취소 요청을 받은 후 취소 지점까지의 진행을 하지 않고 바로 종료한다.

2.1.2절. 쓰레드 취소 종류의 설정

쓰레드 취소 상태가 PTHREAD_CANCEL_ENABLE인 경우 취소의 종류를 결정할 수 있다. 취소 종류의 결정은 pthread_setcanceltype()을 통해서 이루어진다.

int pthread_setcanceltype(int type, int *oldtype);

취소 종류는 type를 통해서 결정된다. PTHREAD_CANCEL_ASYNCHRONOUSPTHREAD_CANCEL_DEFERRED 둘 중 하나를 선택할 수 있다. 전자일 경우 바로 종료하며, 후자의 경우 취소 지점을 벗어날 때까지 기다리게 된다. oldtype를 이용해서 이전 취소 타입을 얻어 올 수 있다. NULL이라면 받아오지 않는다. 이 함수는 당연하지만 취소 상태가 PTHREAD_CANCEL_DISABLE라면 의미 없는 함수다.

2.1.3절. 취소지점

쓰레드에게 취소 요청이 왔다고 해서 무조건 취소해 버리면 문제가 생길 수도 있다. 어떤 일을 처리하고 있는 중에 취소 요청이 전달했는데, 별로 중요하지 않는 (무시해도 될 만한) 일이라면 중단 후 바로 취소해도 되겠지만 중요한 일을 처리하는 중이라면 일을 처리한 후 종료해야 할 것이다. 이 마지 노선이 취소 지점이다.

취소 지점으로 설정될 수 있는 영역은 다음과 같다.

pthread_join(3)
pthread_cond_wait(3)
pthread_cond_timedwait(3)
pthread_testcancel(3)
sem_wait(3)
sigwait(3)

pthread_setcancelstate()에 의해서 PTHREAD_CANCEL_ENABLE 상태로 되어 있다면 취소 지점을 무시하고 즉시 종료 된다. PTHREAD_CANCEL_DISABLE로 되어 있다면 위의 취소 지점을 벗어날 때까지 기다린다. 즉 취소 요청을 받은 쓰레드가 pthread_cond_wait()에서 조건 변수를 기다리는고 있다면 조건 변수를 받을 때까지 취소를 유보하게 된다.

2.2절. 쓰레드 기본 취소 상태와 취소 종류

별 다른 설정이 없을 경우 pthread_create()로 만들어 지는 쓰레드는 PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DEFERRED로 상태로 생성된다.


2.3절. 쓰레드 종료시 자원 정리

pthread_cancel() 등을 통해서 종료 통보를 받은 쓰레드는 종료하기 전에 여러 가지 일을 해주어야 할 것이다. 뭐 간단한 쓰레드라면 관계 없겠지만 복잡하게 얽혀 있는 멀티 쓰레드 프로그램이라면 이런 저런 정리해줘야 할 것들이 많을 것이다.

2.3.1절. 쓰레드 종료시 자원 해제

쓰레드에서 malloc() 등을 호출해서 메모리 공간을 확보했다거나 DB나 파일, 소켓 등을 열어서 작업했다면 반드시 이들 자원을 해제시켜줘야 한다. 간단하게 생각하자면 쓰레드 종료 시점에서 free(), close(), DB라면 이런 저런 정리를 해주면 될 것이다. 그러나 pthrad_cancel() 등에 의해서 작업 중간에 요청을 받았다면 그리 간단한 문제가 아니다. 쓰레드 마지막까지 루틴을 진행할 수 없기 때문이다. 이럴 경우를 대비해서 pthread_cleanup_push(), pthread_cleanup_pop()와 같은 함수를 제공한다.

이 함수들을 이용해서 쓰레드가 종료할 때 호출해야 할 함수를 지정할 수 있다. 그러므로 프로그래머는 이들 함수에 자원 해제와 같은 필요한 코드를 넣어두기만 하면 된다. 이들 함수에 대한 자세한 내용은 Pthread_API를 참고하기 바란다.

2.4절. 총정리

지금까지의 내용을 예제를 통해서 정리해보도록 하자.

main 쓰레드는 thread_func 함수를 실행시킨다. thread_func 함수는 pthread_cond_wait()에서 신호가 발생하기를 기다리게 된다. 잠시 후 main 쓰레드는 pthread_cancel()을 이용해서 thread_func 쓰레드에 취소 요청을 하게 된다. 위의 경우 thread_func 쓰레드는 취소 상태가 PTHREAD_CANCEL_DISABLE로 되어 있기 때문에 취소 지점 등은 무시하고 바로 종료된다. 이때 pthread_cleanup_push()에 등록된 clean_up 함수가 실행되는 걸 확인할 수 있을 것이다.

PTHREAD_CANCEL_ENABLE로 되어 있을 경우 취소 요청을 받아들이기 때문에 취소 요청이 들어오더라도 thread_func()가 현재 종료 지점에 머물러 있기 때문에 곧바로 종료하지 않는다. main 쓰레드에서 pthread_cond_signal()를 호출해서 thread_func()가 cond_wait 상태를 벗어난 후 종료된다. 물론 cleanup 함수도 실행된다.

3절. 참고문헌

1. pthread API 레퍼런스
2. mutex와 조건변수

This article comes from Joinc

http://www.joinc.co.kr

'프로그래밍 > 시스템 프로그래밍' 카테고리의 다른 글

YoLinux Tutorial: POSIX thread (pthread) libraries  (0) 2006.06.02
[본문스크랩] 스레드 개요  (0) 2006.06.02
쓰레드와 시그널  (0) 2006.06.02
Pthread API Reference  (0) 2006.06.02
쓰레드 풀 작성  (0) 2006.06.02