/src/strongswan/src/libstrongswan/threading/thread.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2009-2012 Tobias Brunner |
3 | | * |
4 | | * Copyright (C) secunet Security Networks AG |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify it |
7 | | * under the terms of the GNU General Public License as published by the |
8 | | * Free Software Foundation; either version 2 of the License, or (at your |
9 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, but |
12 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
13 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | | * for more details. |
15 | | */ |
16 | | |
17 | | #define _GNU_SOURCE |
18 | | #include <pthread.h> |
19 | | #include <signal.h> |
20 | | |
21 | | #ifdef HAVE_GETTID |
22 | | #include <sys/types.h> |
23 | | #include <unistd.h> |
24 | | #endif |
25 | | |
26 | | #ifdef HAVE_SYS_GETTID |
27 | | #include <sys/syscall.h> |
28 | | static inline pid_t gettid() |
29 | | { |
30 | | return syscall(SYS_gettid); |
31 | | } |
32 | | #endif |
33 | | |
34 | | #include <library.h> |
35 | | #include <utils/debug.h> |
36 | | |
37 | | #include <threading/thread_value.h> |
38 | | #include <threading/mutex.h> |
39 | | #include <collections/linked_list.h> |
40 | | |
41 | | #include "thread.h" |
42 | | |
43 | | typedef struct private_thread_t private_thread_t; |
44 | | |
45 | | struct private_thread_t { |
46 | | /** |
47 | | * Public interface. |
48 | | */ |
49 | | thread_t public; |
50 | | |
51 | | /** |
52 | | * Identifier of this thread (human-readable/thread ID). |
53 | | */ |
54 | | u_int id; |
55 | | |
56 | | /** |
57 | | * ID of the underlying thread. |
58 | | */ |
59 | | pthread_t thread_id; |
60 | | |
61 | | /** |
62 | | * Main function of this thread (NULL for the main thread). |
63 | | */ |
64 | | thread_main_t main; |
65 | | |
66 | | /** |
67 | | * Argument for the main function. |
68 | | */ |
69 | | void *arg; |
70 | | |
71 | | /** |
72 | | * Stack of cleanup handlers. |
73 | | */ |
74 | | linked_list_t *cleanup_handlers; |
75 | | |
76 | | /** |
77 | | * Mutex to make modifying thread properties safe. |
78 | | */ |
79 | | mutex_t *mutex; |
80 | | |
81 | | /** |
82 | | * TRUE if this thread has been detached or joined, i.e. can be cleaned |
83 | | * up after terminating. |
84 | | */ |
85 | | bool detached_or_joined; |
86 | | |
87 | | /** |
88 | | * TRUE if the threads has terminated (canceled, via thread_exit or |
89 | | * returned from the main function) |
90 | | */ |
91 | | bool terminated; |
92 | | |
93 | | }; |
94 | | |
95 | | typedef struct { |
96 | | /** |
97 | | * Cleanup callback function. |
98 | | */ |
99 | | thread_cleanup_t cleanup; |
100 | | |
101 | | /** |
102 | | * Argument provided to the cleanup function. |
103 | | */ |
104 | | void *arg; |
105 | | |
106 | | } cleanup_handler_t; |
107 | | |
108 | | |
109 | | /** |
110 | | * Next thread ID. |
111 | | */ |
112 | | static u_int next_id; |
113 | | |
114 | | /** |
115 | | * Mutex to safely access the next thread ID. |
116 | | */ |
117 | | static mutex_t *id_mutex; |
118 | | |
119 | | /** |
120 | | * Store the thread object in a thread-specific value. |
121 | | */ |
122 | | static thread_value_t *current_thread; |
123 | | |
124 | | |
125 | | #ifndef HAVE_PTHREAD_CANCEL |
126 | | /* if pthread_cancel is not available, we emulate it using a signal */ |
127 | | #ifdef ANDROID |
128 | | #define SIG_CANCEL SIGUSR2 |
129 | | #else |
130 | | #define SIG_CANCEL (SIGRTMIN+7) |
131 | | #endif |
132 | | |
133 | | /* the signal handler for SIG_CANCEL uses pthread_exit to terminate the |
134 | | * "canceled" thread */ |
135 | | static void cancel_signal_handler(int sig) |
136 | | { |
137 | | pthread_exit(NULL); |
138 | | } |
139 | | #endif |
140 | | |
141 | | |
142 | | /** |
143 | | * Destroy an internal thread object. |
144 | | * |
145 | | * @note The mutex of this thread object has to be locked, it gets unlocked |
146 | | * automatically. |
147 | | */ |
148 | | static void thread_destroy(private_thread_t *this) |
149 | 3.51k | { |
150 | 3.51k | if (!this->terminated || !this->detached_or_joined) |
151 | 0 | { |
152 | 0 | this->mutex->unlock(this->mutex); |
153 | 0 | return; |
154 | 0 | } |
155 | 3.51k | this->cleanup_handlers->destroy(this->cleanup_handlers); |
156 | 3.51k | this->mutex->unlock(this->mutex); |
157 | 3.51k | this->mutex->destroy(this->mutex); |
158 | 3.51k | free(this); |
159 | 3.51k | } |
160 | | |
161 | | /** |
162 | | * Determine the ID of the current thread |
163 | | */ |
164 | | static u_int get_thread_id() |
165 | 3.51k | { |
166 | 3.51k | u_int id; |
167 | | |
168 | | #if defined(USE_THREAD_IDS) && defined(HAVE_GETTID) |
169 | | id = gettid(); |
170 | | #else |
171 | 3.51k | id_mutex->lock(id_mutex); |
172 | 3.51k | id = next_id++; |
173 | 3.51k | id_mutex->unlock(id_mutex); |
174 | 3.51k | #endif |
175 | 3.51k | return id; |
176 | 3.51k | } |
177 | | |
178 | | METHOD(thread_t, cancel, void, |
179 | | private_thread_t *this) |
180 | 0 | { |
181 | 0 | this->mutex->lock(this->mutex); |
182 | 0 | if (pthread_equal(this->thread_id, pthread_self())) |
183 | 0 | { |
184 | 0 | this->mutex->unlock(this->mutex); |
185 | 0 | DBG1(DBG_LIB, "!!! CANNOT CANCEL CURRENT THREAD !!!"); |
186 | 0 | return; |
187 | 0 | } |
188 | 0 | #ifdef HAVE_PTHREAD_CANCEL |
189 | 0 | pthread_cancel(this->thread_id); |
190 | | #else |
191 | | pthread_kill(this->thread_id, SIG_CANCEL); |
192 | | #endif /* HAVE_PTHREAD_CANCEL */ |
193 | 0 | this->mutex->unlock(this->mutex); |
194 | 0 | } |
195 | | |
196 | | METHOD(thread_t, kill_, void, |
197 | | private_thread_t *this, int sig) |
198 | 0 | { |
199 | 0 | this->mutex->lock(this->mutex); |
200 | 0 | if (pthread_equal(this->thread_id, pthread_self())) |
201 | 0 | { |
202 | | /* it might actually be possible to send a signal to pthread_self (there |
203 | | * is an example in raise(3) describing that), the problem is though, |
204 | | * that the thread only returns here after the signal handler has |
205 | | * returned, so depending on the signal, the lock might not get |
206 | | * unlocked. */ |
207 | 0 | this->mutex->unlock(this->mutex); |
208 | 0 | DBG1(DBG_LIB, "!!! CANNOT SEND SIGNAL TO CURRENT THREAD !!!"); |
209 | 0 | return; |
210 | 0 | } |
211 | 0 | pthread_kill(this->thread_id, sig); |
212 | 0 | this->mutex->unlock(this->mutex); |
213 | 0 | } |
214 | | |
215 | | METHOD(thread_t, detach, void, |
216 | | private_thread_t *this) |
217 | 0 | { |
218 | 0 | this->mutex->lock(this->mutex); |
219 | 0 | pthread_detach(this->thread_id); |
220 | 0 | this->detached_or_joined = TRUE; |
221 | 0 | thread_destroy(this); |
222 | 0 | } |
223 | | |
224 | | METHOD(thread_t, join, void*, |
225 | | private_thread_t *this) |
226 | 0 | { |
227 | 0 | pthread_t thread_id; |
228 | 0 | void *val; |
229 | |
|
230 | 0 | this->mutex->lock(this->mutex); |
231 | 0 | if (pthread_equal(this->thread_id, pthread_self())) |
232 | 0 | { |
233 | 0 | this->mutex->unlock(this->mutex); |
234 | 0 | DBG1(DBG_LIB, "!!! CANNOT JOIN CURRENT THREAD !!!"); |
235 | 0 | return NULL; |
236 | 0 | } |
237 | 0 | if (this->detached_or_joined) |
238 | 0 | { |
239 | 0 | this->mutex->unlock(this->mutex); |
240 | 0 | DBG1(DBG_LIB, "!!! CANNOT JOIN DETACHED THREAD !!!"); |
241 | 0 | return NULL; |
242 | 0 | } |
243 | 0 | thread_id = this->thread_id; |
244 | 0 | this->detached_or_joined = TRUE; |
245 | 0 | if (this->terminated) |
246 | 0 | { |
247 | | /* thread has terminated before the call to join */ |
248 | 0 | thread_destroy(this); |
249 | 0 | } |
250 | 0 | else |
251 | 0 | { |
252 | | /* thread_destroy is called when the thread terminates normally */ |
253 | 0 | this->mutex->unlock(this->mutex); |
254 | 0 | } |
255 | 0 | pthread_join(thread_id, &val); |
256 | |
|
257 | 0 | return val; |
258 | 0 | } |
259 | | |
260 | | /** |
261 | | * Create an internal thread object. |
262 | | */ |
263 | | static private_thread_t *thread_create_internal() |
264 | 3.51k | { |
265 | 3.51k | private_thread_t *this; |
266 | | |
267 | 3.51k | INIT(this, |
268 | 3.51k | .public = { |
269 | 3.51k | .cancel = _cancel, |
270 | 3.51k | .kill = _kill_, |
271 | 3.51k | .detach = _detach, |
272 | 3.51k | .join = _join, |
273 | 3.51k | }, |
274 | 3.51k | .cleanup_handlers = linked_list_create(), |
275 | 3.51k | .mutex = mutex_create(MUTEX_TYPE_DEFAULT), |
276 | 3.51k | ); |
277 | | |
278 | 3.51k | return this; |
279 | 3.51k | } |
280 | | |
281 | | /** |
282 | | * Remove and run all cleanup handlers in reverse order. |
283 | | */ |
284 | | static void thread_cleanup_popall_internal(private_thread_t *this) |
285 | 0 | { |
286 | 0 | cleanup_handler_t *handler; |
287 | |
|
288 | 0 | while (this->cleanup_handlers->remove_last(this->cleanup_handlers, |
289 | 0 | (void**)&handler) == SUCCESS) |
290 | 0 | { |
291 | 0 | handler->cleanup(handler->arg); |
292 | 0 | free(handler); |
293 | 0 | } |
294 | 0 | } |
295 | | |
296 | | /** |
297 | | * Main cleanup function for threads. |
298 | | */ |
299 | | static void thread_cleanup(private_thread_t *this) |
300 | 0 | { |
301 | 0 | thread_cleanup_popall_internal(this); |
302 | 0 | this->mutex->lock(this->mutex); |
303 | 0 | this->terminated = TRUE; |
304 | 0 | thread_destroy(this); |
305 | 0 | } |
306 | | |
307 | | /** |
308 | | * Main function wrapper for threads. |
309 | | * |
310 | | * Excluded from AddressSanitizer because some newer versions have an issue that |
311 | | * causes an "AddressSanitizer CHECK failed" error for canceled threads. |
312 | | */ |
313 | | ADDRESS_SANITIZER_EXCLUDE |
314 | | static void *thread_main(private_thread_t *this) |
315 | 0 | { |
316 | 0 | void *res; |
317 | |
|
318 | 0 | this->id = get_thread_id(); |
319 | |
|
320 | 0 | current_thread->set(current_thread, this); |
321 | 0 | pthread_cleanup_push((thread_cleanup_t)thread_cleanup, this); |
322 | | |
323 | | /* TODO: this is not 100% portable as pthread_t is an opaque type (i.e. |
324 | | * could be of any size, or even a struct) */ |
325 | 0 | #ifdef HAVE_GETTID |
326 | 0 | DBG2(DBG_LIB, "created thread %.2d [%u]", |
327 | 0 | this->id, gettid()); |
328 | | #elif defined(WIN32) |
329 | | DBG2(DBG_LIB, "created thread %.2d [%p]", |
330 | | this->id, this->thread_id.p); |
331 | | #else |
332 | | DBG2(DBG_LIB, "created thread %.2d [%lx]", |
333 | | this->id, (u_long)this->thread_id); |
334 | | #endif |
335 | |
|
336 | 0 | res = this->main(this->arg); |
337 | 0 | pthread_cleanup_pop(TRUE); |
338 | | |
339 | 0 | return res; |
340 | 0 | } |
341 | | |
342 | | /** |
343 | | * Described in header. |
344 | | */ |
345 | | thread_t *thread_create(thread_main_t main, void *arg) |
346 | 0 | { |
347 | 0 | private_thread_t *this = thread_create_internal(); |
348 | |
|
349 | 0 | this->main = main; |
350 | 0 | this->arg = arg; |
351 | |
|
352 | 0 | if (pthread_create(&this->thread_id, NULL, (void*)thread_main, this) != 0) |
353 | 0 | { |
354 | 0 | DBG1(DBG_LIB, "failed to create thread!"); |
355 | 0 | this->mutex->lock(this->mutex); |
356 | 0 | this->terminated = TRUE; |
357 | 0 | this->detached_or_joined = TRUE; |
358 | 0 | thread_destroy(this); |
359 | 0 | return NULL; |
360 | 0 | } |
361 | | |
362 | 0 | return &this->public; |
363 | 0 | } |
364 | | |
365 | | /** |
366 | | * Described in header. |
367 | | */ |
368 | | thread_t *thread_current() |
369 | 3.51k | { |
370 | 3.51k | private_thread_t *this; |
371 | | |
372 | 3.51k | this = (private_thread_t*)current_thread->get(current_thread); |
373 | 3.51k | if (!this) |
374 | 0 | { |
375 | 0 | this = thread_create_internal(); |
376 | 0 | this->id = get_thread_id(); |
377 | 0 | current_thread->set(current_thread, (void*)this); |
378 | 0 | } |
379 | 3.51k | return &this->public; |
380 | 3.51k | } |
381 | | |
382 | | /** |
383 | | * Described in header. |
384 | | */ |
385 | | u_int thread_current_id() |
386 | 0 | { |
387 | 0 | private_thread_t *this = (private_thread_t*)thread_current(); |
388 | |
|
389 | 0 | return this ? this->id : 0; |
390 | 0 | } |
391 | | |
392 | | /** |
393 | | * Described in header. |
394 | | */ |
395 | | void thread_cleanup_push(thread_cleanup_t cleanup, void *arg) |
396 | 0 | { |
397 | 0 | private_thread_t *this = (private_thread_t*)thread_current(); |
398 | 0 | cleanup_handler_t *handler; |
399 | |
|
400 | 0 | INIT(handler, |
401 | 0 | .cleanup = cleanup, |
402 | 0 | .arg = arg, |
403 | 0 | ); |
404 | |
|
405 | 0 | this->cleanup_handlers->insert_last(this->cleanup_handlers, handler); |
406 | 0 | } |
407 | | |
408 | | /** |
409 | | * Described in header. |
410 | | */ |
411 | | void thread_cleanup_pop(bool execute) |
412 | 0 | { |
413 | 0 | private_thread_t *this = (private_thread_t*)thread_current(); |
414 | 0 | cleanup_handler_t *handler; |
415 | |
|
416 | 0 | if (this->cleanup_handlers->remove_last(this->cleanup_handlers, |
417 | 0 | (void**)&handler) != SUCCESS) |
418 | 0 | { |
419 | 0 | DBG1(DBG_LIB, "!!! THREAD CLEANUP ERROR !!!"); |
420 | 0 | return; |
421 | 0 | } |
422 | | |
423 | 0 | if (execute) |
424 | 0 | { |
425 | 0 | handler->cleanup(handler->arg); |
426 | 0 | } |
427 | 0 | free(handler); |
428 | 0 | } |
429 | | |
430 | | /** |
431 | | * Described in header. |
432 | | */ |
433 | | void thread_cleanup_popall() |
434 | 0 | { |
435 | 0 | private_thread_t *this = (private_thread_t*)thread_current(); |
436 | |
|
437 | 0 | thread_cleanup_popall_internal(this); |
438 | 0 | } |
439 | | |
440 | | /** |
441 | | * Described in header. |
442 | | */ |
443 | | bool thread_cancelability(bool enable) |
444 | 0 | { |
445 | 0 | #ifdef HAVE_PTHREAD_CANCEL |
446 | 0 | int old; |
447 | |
|
448 | 0 | pthread_setcancelstate(enable ? PTHREAD_CANCEL_ENABLE |
449 | 0 | : PTHREAD_CANCEL_DISABLE, &old); |
450 | |
|
451 | 0 | return old == PTHREAD_CANCEL_ENABLE; |
452 | | #else |
453 | | sigset_t new, old; |
454 | | |
455 | | sigemptyset(&new); |
456 | | sigaddset(&new, SIG_CANCEL); |
457 | | pthread_sigmask(enable ? SIG_UNBLOCK : SIG_BLOCK, &new, &old); |
458 | | |
459 | | return sigismember(&old, SIG_CANCEL) == 0; |
460 | | #endif /* HAVE_PTHREAD_CANCEL */ |
461 | 0 | } |
462 | | |
463 | | /** |
464 | | * Described in header. |
465 | | */ |
466 | | void thread_cancellation_point() |
467 | 0 | { |
468 | 0 | bool old = thread_cancelability(TRUE); |
469 | |
|
470 | 0 | #ifdef HAVE_PTHREAD_CANCEL |
471 | 0 | pthread_testcancel(); |
472 | 0 | #endif /* HAVE_PTHREAD_CANCEL */ |
473 | 0 | thread_cancelability(old); |
474 | 0 | } |
475 | | |
476 | | /** |
477 | | * Described in header. |
478 | | */ |
479 | | void thread_exit(void *val) |
480 | 0 | { |
481 | 0 | pthread_exit(val); |
482 | 0 | } |
483 | | |
484 | | /** |
485 | | * A dummy thread value that reserved pthread_key_t value "0". A buggy PKCS#11 |
486 | | * library mangles this key, without owning it, so we allocate it for them. |
487 | | */ |
488 | | static thread_value_t *dummy1; |
489 | | |
490 | | /** |
491 | | * Described in header. |
492 | | */ |
493 | | void threads_init() |
494 | 3.51k | { |
495 | 3.51k | private_thread_t *main_thread = thread_create_internal(); |
496 | | |
497 | 3.51k | dummy1 = thread_value_create(NULL); |
498 | | |
499 | 3.51k | next_id = 0; |
500 | 3.51k | main_thread->thread_id = pthread_self(); |
501 | 3.51k | current_thread = thread_value_create(NULL); |
502 | 3.51k | current_thread->set(current_thread, (void*)main_thread); |
503 | 3.51k | id_mutex = mutex_create(MUTEX_TYPE_DEFAULT); |
504 | 3.51k | main_thread->id = get_thread_id(); |
505 | | |
506 | | #ifndef HAVE_PTHREAD_CANCEL |
507 | | { /* install a signal handler for our custom SIG_CANCEL */ |
508 | | struct sigaction action = { |
509 | | .sa_handler = cancel_signal_handler |
510 | | }; |
511 | | sigaction(SIG_CANCEL, &action, NULL); |
512 | | } |
513 | | #endif /* HAVE_PTHREAD_CANCEL */ |
514 | 3.51k | } |
515 | | |
516 | | /** |
517 | | * Described in header. |
518 | | */ |
519 | | void threads_deinit() |
520 | 3.51k | { |
521 | 3.51k | private_thread_t *main_thread = (private_thread_t*)thread_current(); |
522 | | |
523 | 3.51k | dummy1->destroy(dummy1); |
524 | | |
525 | 3.51k | main_thread->mutex->lock(main_thread->mutex); |
526 | 3.51k | main_thread->terminated = TRUE; |
527 | 3.51k | main_thread->detached_or_joined = TRUE; |
528 | 3.51k | thread_destroy(main_thread); |
529 | 3.51k | current_thread->destroy(current_thread); |
530 | 3.51k | id_mutex->destroy(id_mutex); |
531 | 3.51k | } |