리눅스

pthread에서 메모리 침범과 pthread_cancel

개발새발 2018. 1. 21. 21:15
반응형

메인 스레드가 join을 통해 다른 스레드들을 기다릴 수 없는 상황이라면(join없이 detach를 통해 스레드가 독립적으로 일을 할 때)

프로세스를 종료하는 시점에 A 스레드가 전역변수를(또는 다른 스레드의 리소스) 접근 할 때 문제가 발생할 수 있다.

(이미 해제 된 메모리를 접근 하려 하기 때문에 SIGSEGV나 SIGABRT가 발생 할 수 있음)




프로세스가 SIGTERM 시그널을 받았거나 앱라이프 사이클에서 terminate시점이라면 pthread_cancel을 통해 스레드들을 먼저 종료해주어야 한다.(+스레드에서 쓰던 메모리도 회수)


[pthread_cancel 예제 코드]




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
 
int temp;
 
 
 
pthread_mutex_t mutex_lock;
 
 
 
void clean_up(void *arg)
 
{
 
    //free resource in this function
 
}
 
 
 
void * th1(void *data)
 
{
 
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 
    pthread_cleanup_push(clean_up, NULL);//pthread_cancel 콜백 함수 등록
 
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);//pthread_cancel시 바로 종료
 
    
 
    for(int i=0;i<100;i++){
 
        pthread_mutex_lock(&mutex_lock);
 
        temp++;
 
        printf("th1 temp:%d\n",temp);
 
        pthread_mutex_unlock(&mutex_lock);
 
        sleep(1);
 
    }
 
    return NULL;
 
}
 
 
 
int main(void){
 
    pthread_t pid[2];
 
    pthread_attr_t attr;
 
 
 
    int thr_id;
 
    int status;
 
    temp=0;
 
 
 
    pthread_mutex_init(&mutex_lock, NULL);
 
    pthread_attr_init(&attr);
 
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
 
 
 
    thr_id = pthread_create(&pid[0], &attr, th1, NULL);
 
    if (thr_id < 0)
 
    {
 
        perror("thread create error : ");
 
        exit(0);
 
    }
 
 
 
    thr_id = pthread_create(&pid[1], &attr, th1, NULL);
 
    if (thr_id < 0)
 
    {
 
        perror("thread create error : ");
 
        exit(0);
 
    }
 
    for(int i=0;i<10;i++){
 
        printf("Main working...\n");
 
        if(i==5){//메인함수 종료 조건
 
            pthread_cancle(pid[0]);
 
            pthread_cancel(pid[1]);
 
            printf("cancel %d %d\n",pid[0],pid[1]);
 
            break;
 
        }
 
        sleep(1);
 
    }
 
    printf("Main Exit\n");
 
    return 0;
 
}
cs
반응형