• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *   http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <pthread.h>
17 #include <stdlib.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20 #include "functionalext.h"
21 
22 #define TEST_THREAD_SLEEP 3
23 
24 pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
25 static int gprepare_flag = 0;
26 static int gparent_flag = 0;
27 static int gchild_flag = 0;
28 
reset_data(void)29 void reset_data(void)
30 {
31     gprepare_flag = 0;
32     gparent_flag = 0;
33     gchild_flag = 0;
34 }
35 
prepare(void)36 static void prepare(void)
37 {
38     int ret = pthread_mutex_lock(&glock);
39     EXPECT_EQ("pthread_atfork prepare", ret, 0);
40     gprepare_flag++;
41 }
42 
parent(void)43 static void parent(void)
44 {
45     int ret = pthread_mutex_unlock(&glock);
46     EXPECT_EQ("pthread_atfork prepare", ret, 0);
47     gparent_flag++;
48 }
49 
child(void)50 static void child(void)
51 {
52     int ret = pthread_mutex_unlock(&glock);
53     EXPECT_EQ("pthread_atfork prepare", ret, 0);
54     gchild_flag++;
55 }
56 
thread_fun(void * arg)57 static void *thread_fun(void *arg)
58 {
59 #ifdef FEATURE_PTHREAD_CANCEL
60     while (1) {
61         pthread_testcancel();
62         pthread_mutex_lock(&glock);
63         sleep(TEST_THREAD_SLEEP);
64         pthread_mutex_unlock(&glock);
65         sleep(1);
66     }
67 #else
68     pthread_mutex_lock(&glock);
69     sleep(TEST_THREAD_SLEEP);
70     pthread_mutex_unlock(&glock);
71     sleep(1);
72 #endif
73     return NULL;
74 }
75 
76 /**
77  * @tc.name      : pthread_atfork_0100
78  * @tc.desc      : Provide a callback to test the relationship between pthread_atfork and fork
79  * @tc.level     : Level 1
80  */
pthread_atfork_0100(void)81 void pthread_atfork_0100(void)
82 {
83     reset_data();
84 #ifdef FEATURE_PTHREAD_CANCEL
85     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
86     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
87 #endif
88     pthread_t tid;
89     int ret = pthread_create(&tid, NULL, thread_fun, NULL);
90     EXPECT_EQ("pthread_atfork_0100", ret, CMPFLAG);
91     if (ret != 0) {
92         return;
93     }
94 
95     ret = pthread_atfork(prepare, parent, child);
96     EXPECT_EQ("pthread_atfork_0100", ret, CMPFLAG);
97     if (ret != 0) {
98         return;
99     }
100     sleep(1);
101 
102     pid_t pid = fork();
103     if (pid == 0) {
104         pthread_mutex_lock(&glock);
105         sleep(1);
106         pthread_mutex_unlock(&glock);
107         EXPECT_EQ("pthread_atfork_0100", gchild_flag, 1);
108         _exit(0);
109     } else if (pid > 0) {
110 #ifdef FEATURE_PTHREAD_CANCEL
111         wait(NULL);
112         pthread_cancel(tid);
113 #endif
114         pthread_join(tid, NULL);
115 
116         EXPECT_EQ("pthread_atfork_0100", gprepare_flag, 1);
117         EXPECT_EQ("pthread_atfork_0100", gparent_flag, 1);
118     } else {
119         EXPECT_FALSE("pthread_atfork_0100", 1);
120     }
121 }
122 
123 /**
124  * @tc.name      : pthread_atfork_0200
125  * @tc.desc      : No callback is provided, test the relationship between pthread_atfork and fork
126  * @tc.level     : Level 2
127  */
pthread_atfork_0200(void)128 void pthread_atfork_0200(void)
129 {
130     reset_data();
131     int ret = pthread_atfork(NULL, NULL, NULL);
132     EXPECT_EQ("pthread_atfork_0200", ret, CMPFLAG);
133     if (ret != 0) {
134         return;
135     }
136 
137     pid_t pid = fork();
138     if (pid == 0) {
139         EXPECT_EQ("pthread_atfork_0200", gchild_flag, 0);
140         _exit(0);
141     } else if (pid > 0) {
142         wait(NULL);
143 
144         EXPECT_EQ("pthread_atfork_0200", gprepare_flag, 0);
145         EXPECT_EQ("pthread_atfork_0200", gparent_flag, 0);
146     } else {
147         EXPECT_FALSE("pthread_atfork_0200", 1);
148     }
149 }
150 
main(void)151 int main(void)
152 {
153     pthread_atfork_0200();
154     pthread_atfork_0100();
155     return t_status;
156 }