diff options
author | Tobias Brunner <tobias@strongswan.org> | 2009-12-22 10:51:11 +0100 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2009-12-23 17:03:42 +0100 |
commit | 85202e8795561d023c83d2b2c32c25a2a720fc04 (patch) | |
tree | cc346f137cdaddfbb171b5e01adc71338769ad25 /src | |
parent | b2944d71ca15b796c021a6cf89a8c67e46e2444a (diff) | |
download | strongswan-85202e8795561d023c83d2b2c32c25a2a720fc04.tar.bz2 strongswan-85202e8795561d023c83d2b2c32c25a2a720fc04.tar.xz |
Added a workaround for the missing pthread_cancel on Android.
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/threading/thread.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c index 14f92dc8c..f2028dfe0 100644 --- a/src/libstrongswan/threading/thread.c +++ b/src/libstrongswan/threading/thread.c @@ -113,6 +113,18 @@ static mutex_t *id_mutex; */ static thread_value_t *current_thread; +#ifndef HAVE_PTHREAD_CANCEL +/* if pthread_cancel is not available, we emulate it using a signal */ +#define SIG_CANCEL (SIGRTMIN+7) + +/* the signal handler for SIG_CANCEL uses pthread_exit to terminate the + * "cancelled" thread */ +static void cancel_signal_handler(int sig) +{ + pthread_exit(NULL); +} +#endif + /** * Destroy an internal thread object. @@ -146,7 +158,11 @@ static void cancel(private_thread_t *this) DBG1("!!! CANNOT CANCEL CURRENT THREAD !!!"); return; } +#ifdef HAVE_PTHREAD_CANCEL pthread_cancel(this->thread_id); +#else + pthread_kill(this->thread_id, SIG_CANCEL); +#endif /* HAVE_PTHREAD_CANCEL */ this->mutex->unlock(this->mutex); } @@ -355,10 +371,18 @@ void thread_cleanup_pop(bool execute) */ bool thread_cancelability(bool enable) { +#ifdef HAVE_PTHREAD_CANCEL int old; pthread_setcancelstate(enable ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE, &old); return old == PTHREAD_CANCEL_ENABLE; +#else + sigset_t new, old; + sigemptyset(&new); + sigaddset(&new, SIG_CANCEL); + pthread_sigmask(enable ? SIG_UNBLOCK : SIG_BLOCK, &new, &old); + return sigismember(&old, SIG_CANCEL) == 0; +#endif /* HAVE_PTHREAD_CANCEL */ } /** @@ -367,7 +391,9 @@ bool thread_cancelability(bool enable) void thread_cancellation_point() { bool old = thread_cancelability(TRUE); +#ifdef HAVE_PTHREAD_CANCEL pthread_testcancel(); +#endif /* HAVE_PTHREAD_CANCEL */ thread_cancelability(old); } @@ -390,6 +416,15 @@ void threads_init() current_thread = thread_value_create(NULL); current_thread->set(current_thread, (void*)main_thread); id_mutex = mutex_create(MUTEX_TYPE_DEFAULT); + +#ifndef HAVE_PTHREAD_CANCEL + { /* install a signal handler for our custom SIG_CANCEL */ + struct sigaction action = { + .sa_handler = cancel_signal_handler + }; + sigaction(SIG_CANCEL, &action, NULL); + } +#endif /* HAVE_PTHREAD_CANCEL */ } /** |