aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2009-12-22 10:51:11 +0100
committerTobias Brunner <tobias@strongswan.org>2009-12-23 17:03:42 +0100
commit85202e8795561d023c83d2b2c32c25a2a720fc04 (patch)
treecc346f137cdaddfbb171b5e01adc71338769ad25 /src
parentb2944d71ca15b796c021a6cf89a8c67e46e2444a (diff)
downloadstrongswan-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.c35
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 */
}
/**