[Linux Programming] 스레드만 종료 / pthread_cleanup_push, pthread_cleanup_pop으로 마무리 처리부 등록하기
* 프로세스에서 스레드만 종료시키고자 하는 경우
1. 스레드 함수에서 return
2. 스레드에서 pthread_exit 호출
3. 다른 스레드에서 pthread_cancel 호출
* pthread_cancel
한 스레드가 같은 프로세스에 속한 다른 스레드의 취소를 요청할 수 있다.
#include <pthread.h>
int pthread_cancel(pthread_t tid);
>> 인자
첫번째 : 스레드 ID
반환값 : 성공시 0, 실패시 오류번호
* 스레드 종료시 특정 함수들이 호출되도록 설정
- 스레드 마무리 처리부,
스레드 마무리 처리부들은 한 스택에 등록되는데,
이는 마무리 처리부들이 등록된 순서의 역순을 호출된다는 의미(선입후출)
#include <pthrad.h>
void pthread_cleanup_push(void(*rtn)(void *), void *arg);
첫번째 인수 : rtn으로 지정된 마무리 함수를 스택에 등록
두번째 인수 : 마무리 처리부 함수의 인수
void pthread_cleanup_pop(int execute);
첫번째 인수 : 0이 아닌 값을 호출하면 마무리처리부에서 pop을 수행한다.
마무리 처리부가 호출되는 상황
* 스레드가 pthread_exit를 호출했다.
* 스레드가 취소 요청에 반응했다. (다른 스레드에서 pthread_cancel을 호출한 경우)
* 스레드가 execute인수에 0이 아닌 값을 넣어서 pthread_cleanup_pop 함수를 호출했다.
* 이 두 함수에 제약
** 이들은 매크로로 구현 될 수 있기 때문에 둘의 호출은 반드시 한 스레드의 같은 범위 안에서 짝을 이루어야 한다.)
** pthread_cleanup_push, pthread_cleanup_pop은 셋트로 써야 한다.
**** 안그러면 컴파일 시 에러가 난다.
**** 짝을 맞춰주기 위해 pop(0) 방식으로 쓰기도 함
void *thr_fn1(void *arg)
{
pthread_cleanup_push( cleanup, NULL);
pthread_cleanup_pop(0);
pthread_exit((void*)2);
}
예제 프로그램
#include "apue.h"
#include <pthread.h>
void cleanup(void *arg)
{
printf("cleanup : %s\n", (char *)arg);
}
void * thr_fn1(void *arg)
{
printf("thread 1 start\n");
pthread_cleanup_push(cleanup, "thread 1 first handler");
pthread_cleanup_push(cleanup, "thread 1 second handler");
printf("thread 1 push complete\n");
if (arg)
{
return ((void *)1);
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
return ((void *)1);
}
void * thr_fn2(void *arg)
{
printf("thread 2 start \n");
pthread_cleanup_push(cleanup, "thread 2 first handler");
pthread_cleanup_push(cleanup, "thread 2 second handler");
printf("thread 2 push complete\n");
if (arg)
{
pthread_exit((void *)2);
}
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
pthread_exit((void *)2);
}
int main(void)
{
int err;
pthread_t tid1, tid2;
void *tret;
err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);
if (err != 0 )
err_quit("can't create thread 1: %s\n", strerror(err));
err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);
if (err != 0 )
err_quit("cna't create thread 2: %s\n", strerror(err));
err = pthread_join(tid1, &tret);
if (err != 0)
err_quit("can't join with thread 1: %s \n", strerror(err));
printf("thread 1 exit code %d \n", (int)tret);
err = pthread_join(tid2, &tret);
if(err != 0)
err_quit("can't join with thread 2: %s \n", strerror(err));
printf("thread 2 exit code %d\n", (int)tret);
exit(0);
}
$ ./11-5
thread 2 start
thread 1 start
thread 1 push complete
thread 2 push complete
thread 1 exit code 1
cleanup : thread 2 second handler
cleanup : thread 2 first handler
thread 2 exit code 2
return으로 종료된 경우는 스레드 마무리 처리부를 처리하지 않았다.
pthread_exit 로 종료한 경우에 스레드 마무리 처리부를 호출하였다.
출처 : 유닉스고급프로그램 11-5
'리눅스' 카테고리의 다른 글
[컴파일] /user/bin/ld:warning ... (try using -rpath or -rpath-link) 이슈 (0) | 2015.06.04 |
---|---|
vi 들여쓰기, 앞부분에 공백추가/ 블럭지정해서 탭 한번 들여쓰기 (0) | 2014.06.18 |
pthread.h를 include했는데도 undefined reference to `pthread_create' 에러날때 (0) | 2014.06.10 |
[리눅스] 가장 크기가 큰 디렉토리 찾기 (0) | 2014.06.09 |
[리눅스] OpenSSL을 이용한 간단 암호화 (0) | 2014.05.27 |