nsprpub/pr/tests/intrupt.c

branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
equal deleted inserted replaced
-1:000000000000 0:c9bf64670915
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 * File: intrupt.c
8 * Purpose: testing thread interrupts
9 */
10
11 #include "plgetopt.h"
12 #include "prcvar.h"
13 #include "prerror.h"
14 #include "prinit.h"
15 #include "prinrval.h"
16 #include "prio.h"
17 #include "prlock.h"
18 #include "prlog.h"
19 #include "prthread.h"
20 #include "prtypes.h"
21 #include "prnetdb.h"
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #define DEFAULT_TCP_PORT 12500
27
28 static PRLock *ml = NULL;
29 static PRCondVar *cv = NULL;
30
31 static PRBool passed = PR_TRUE;
32 static PRBool debug_mode = PR_FALSE;
33 static PRThreadScope thread_scope = PR_LOCAL_THREAD;
34
35 static void PR_CALLBACK AbortCV(void *arg)
36 {
37 PRStatus rv;
38 PRThread *me = PR_GetCurrentThread();
39
40 /* some other thread (main) is doing the interrupt */
41 PR_Lock(ml);
42 rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT);
43 if (debug_mode) printf( "Expected interrupt on wait CV and ");
44 if (PR_FAILURE == rv)
45 {
46 if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
47 {
48 if (debug_mode) printf("got it\n");
49 }
50 else
51 {
52 if (debug_mode) printf("got random error\n");
53 passed = PR_FALSE;
54 }
55 }
56 else
57 {
58 if (debug_mode) printf("got a successful completion\n");
59 passed = PR_FALSE;
60 }
61
62 rv = PR_WaitCondVar(cv, 10);
63 if (debug_mode)
64 {
65 printf(
66 "Expected success on wait CV and %s\n",
67 (PR_SUCCESS == rv) ? "got it" : "failed");
68 }
69 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
70
71 /* interrupt myself, then clear */
72 PR_Interrupt(me);
73 PR_ClearInterrupt();
74 rv = PR_WaitCondVar(cv, 10);
75 if (debug_mode)
76 {
77 printf("Expected success on wait CV and ");
78 if (PR_FAILURE == rv)
79 {
80 printf(
81 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
82 "got interrupted" : "a random failure");
83 }
84 printf("got it\n");
85 }
86 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
87
88 /* set, then wait - interrupt - then wait again */
89 PR_Interrupt(me);
90 rv = PR_WaitCondVar(cv, 10);
91 if (debug_mode) printf( "Expected interrupt on wait CV and ");
92 if (PR_FAILURE == rv)
93 {
94 if (PR_PENDING_INTERRUPT_ERROR == PR_GetError())
95 {
96 if (debug_mode) printf("got it\n");
97 }
98 else
99 {
100 if (debug_mode) printf("failed\n");
101 passed = PR_FALSE;
102 }
103 }
104 else
105 {
106 if (debug_mode) printf("got a successful completion\n");
107 passed = PR_FALSE;
108 }
109
110 rv = PR_WaitCondVar(cv, 10);
111 if (debug_mode)
112 {
113 printf(
114 "Expected success on wait CV and %s\n",
115 (PR_SUCCESS == rv) ? "got it" : "failed");
116 }
117 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
118
119 PR_Unlock(ml);
120
121 } /* AbortCV */
122
123 static void PR_CALLBACK AbortIO(void *arg)
124 {
125 PRStatus rv;
126 PR_Sleep(PR_SecondsToInterval(2));
127 rv = PR_Interrupt((PRThread*)arg);
128 PR_ASSERT(PR_SUCCESS == rv);
129 } /* AbortIO */
130
131 static void PR_CALLBACK AbortJoin(void *arg)
132 {
133 } /* AbortJoin */
134
135 static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr)
136 {
137 PRStatus rv;
138 PRInt16 port = DEFAULT_TCP_PORT;
139
140 *listner = PR_NewTCPSocket();
141 PR_ASSERT(*listner != NULL);
142 memset(netaddr, 0, sizeof(*netaddr));
143 (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY);
144 (*netaddr).inet.family = PR_AF_INET;
145 do
146 {
147 (*netaddr).inet.port = PR_htons(port);
148 rv = PR_Bind(*listner, netaddr);
149 port += 1;
150 PR_ASSERT(port < (DEFAULT_TCP_PORT + 10));
151 } while (PR_FAILURE == rv);
152
153 rv = PR_Listen(*listner, 5);
154
155 if (PR_GetSockName(*listner, netaddr) < 0) {
156 if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n");
157 passed = PR_FALSE;
158 return;
159 }
160
161 }
162
163 static void PR_CALLBACK IntrBlock(void *arg)
164 {
165 PRStatus rv;
166 PRNetAddr netaddr;
167 PRFileDesc *listner;
168
169 /* some other thread (main) is doing the interrupt */
170 /* block the interrupt */
171 PR_BlockInterrupt();
172 PR_Lock(ml);
173 rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4));
174 PR_Unlock(ml);
175 if (debug_mode)
176 {
177 printf("Expected success on wait CV and ");
178 if (PR_FAILURE == rv)
179 {
180 printf(
181 "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ?
182 "got interrupted" : "got a random failure");
183 } else
184 printf("got it\n");
185 }
186 passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE;
187
188 setup_listen_socket(&listner, &netaddr);
189 PR_UnblockInterrupt();
190 if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
191 {
192 PRInt32 error = PR_GetError();
193 if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
194 if (PR_PENDING_INTERRUPT_ERROR == error)
195 {
196 if (debug_mode) printf("got it\n");
197 }
198 else
199 {
200 if (debug_mode) printf("failed\n");
201 passed = PR_FALSE;
202 }
203 }
204 else
205 {
206 if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
207 passed = PR_FALSE;
208 }
209
210 (void)PR_Close(listner); listner = NULL;
211 } /* TestIntrBlock */
212
213 void PR_CALLBACK Intrupt(void *arg)
214 {
215 PRStatus rv;
216 PRNetAddr netaddr;
217 PRFileDesc *listner;
218 PRThread *abortCV, *abortIO, *abortJoin, *intrBlock;
219
220 ml = PR_NewLock();
221 cv = PR_NewCondVar(ml);
222
223 /* Part I */
224 if (debug_mode) printf("Part I\n");
225 abortCV = PR_CreateThread(
226 PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL,
227 thread_scope, PR_JOINABLE_THREAD, 0);
228
229 PR_Sleep(PR_SecondsToInterval(2));
230 rv = PR_Interrupt(abortCV);
231 PR_ASSERT(PR_SUCCESS == rv);
232 rv = PR_JoinThread(abortCV);
233 PR_ASSERT(PR_SUCCESS == rv);
234
235 /* Part II */
236 if (debug_mode) printf("Part II\n");
237 abortJoin = PR_CreateThread(
238 PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL,
239 thread_scope, PR_JOINABLE_THREAD, 0);
240 PR_Sleep(PR_SecondsToInterval(2));
241 if (debug_mode) printf("Expecting to interrupt an exited thread ");
242 rv = PR_Interrupt(abortJoin);
243 PR_ASSERT(PR_SUCCESS == rv);
244 rv = PR_JoinThread(abortJoin);
245 PR_ASSERT(PR_SUCCESS == rv);
246 if (debug_mode) printf("and succeeded\n");
247
248 /* Part III */
249 if (debug_mode) printf("Part III\n");
250 setup_listen_socket(&listner, &netaddr);
251 abortIO = PR_CreateThread(
252 PR_USER_THREAD, AbortIO, PR_GetCurrentThread(), PR_PRIORITY_NORMAL,
253 thread_scope, PR_JOINABLE_THREAD, 0);
254
255 if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL)
256 {
257 PRInt32 error = PR_GetError();
258 if (debug_mode) printf("Expected interrupt on PR_Accept() and ");
259 if (PR_PENDING_INTERRUPT_ERROR == error)
260 {
261 if (debug_mode) printf("got it\n");
262 }
263 else
264 {
265 if (debug_mode) printf("failed\n");
266 passed = PR_FALSE;
267 }
268 }
269 else
270 {
271 if (debug_mode) printf("Failed to interrupt PR_Accept()\n");
272 passed = PR_FALSE;
273 }
274
275 (void)PR_Close(listner); listner = NULL;
276
277 rv = PR_JoinThread(abortIO);
278 PR_ASSERT(PR_SUCCESS == rv);
279 /* Part VI */
280 if (debug_mode) printf("Part VI\n");
281 intrBlock = PR_CreateThread(
282 PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL,
283 thread_scope, PR_JOINABLE_THREAD, 0);
284
285 PR_Sleep(PR_SecondsToInterval(2));
286 rv = PR_Interrupt(intrBlock);
287 PR_ASSERT(PR_SUCCESS == rv);
288 rv = PR_JoinThread(intrBlock);
289 PR_ASSERT(PR_SUCCESS == rv);
290
291 PR_DestroyCondVar(cv);
292 PR_DestroyLock(ml);
293 } /* Intrupt */
294
295 int main(int argc, char **argv)
296 {
297 PRThread *intrupt;
298 PLOptStatus os;
299 PLOptState *opt = PL_CreateOptState(argc, argv, "dG");
300 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
301 {
302 if (PL_OPT_BAD == os) continue;
303 switch (opt->option)
304 {
305 case 'd': /* debug mode */
306 debug_mode = PR_TRUE;
307 break;
308 case 'G': /* use global threads */
309 thread_scope = PR_GLOBAL_THREAD;
310 break;
311 }
312 }
313 PL_DestroyOptState(opt);
314 PR_STDIO_INIT();
315 intrupt = PR_CreateThread(
316 PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL,
317 thread_scope, PR_JOINABLE_THREAD, 0);
318 if (intrupt == NULL) {
319 fprintf(stderr, "cannot create thread\n");
320 passed = PR_FALSE;
321 } else {
322 PRStatus rv;
323 rv = PR_JoinThread(intrupt);
324 PR_ASSERT(rv == PR_SUCCESS);
325 }
326 printf("%s\n", ((passed) ? "PASSED" : "FAILED"));
327 return ((passed) ? 0 : 1);
328 } /* main */
329
330 /* intrupt.c */

mercurial