From c4407dda5f578ec2f00aba9ae9d5f789cae5a36d Mon Sep 17 00:00:00 2001 From: Andrey Malets Date: Sun, 21 Jan 2018 22:17:25 +0500 Subject: [PATCH 1/2] Avoid pthread_cancel as it may not be defined. Some target platforms, notably Android NDK, do not have pthread_cancel function available, a simple solution using thread signals may be used instead. --- src/sb_thread.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/sb_thread.c b/src/sb_thread.c index 384ddb7..f37aafd 100644 --- a/src/sb_thread.c +++ b/src/sb_thread.c @@ -33,6 +33,8 @@ # include #endif +#include + #include "sb_thread.h" #include "sb_rand.h" #include "sb_logger.h" @@ -84,10 +86,56 @@ void sb_thread_done(void) free(threads); } +struct sb_thread_proxy { + void *(*start_routine) (void *); + void *arg; +}; + +static int thread_cancel_signal = SIGUSR1; + +static void thread_cancel_handler(int sig) +{ +#ifndef PTHREAD_CANCELED +# define PTHREAD_CANCELED ((void *) -1) +#endif + if (sig == thread_cancel_signal) + pthread_exit(PTHREAD_CANCELED); +} + +static int install_thread_signal_handler(void) { + struct sigaction action; + memset(&action, 0, sizeof(action)); + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + action.sa_handler = thread_cancel_handler; + return sigaction(thread_cancel_signal, &action, NULL); +} + +static void* thread_start_routine_proxy(void *arg) { + struct sb_thread_proxy *proxy = arg; + void *(*start_routine) (void *) = proxy->start_routine; + void *real_arg = proxy->arg; + free(proxy); + install_thread_signal_handler(); + return start_routine(real_arg); +} + int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { - return pthread_create(thread, attr, start_routine, arg); + struct sb_thread_proxy *proxy = malloc(sizeof(struct sb_thread_proxy)); + if (!proxy) + { + return EXIT_FAILURE; + } + proxy->start_routine = start_routine; + proxy->arg = arg; + int rv = pthread_create(thread, attr, thread_start_routine_proxy, proxy); + if (rv) + { + free(proxy); + } + return rv; } int sb_thread_join(pthread_t thread, void **retval) @@ -97,7 +145,7 @@ int sb_thread_join(pthread_t thread, void **retval) int sb_thread_cancel(pthread_t thread) { - return pthread_cancel(thread); + return pthread_kill(thread, thread_cancel_signal); } int sb_thread_create_workers(void *(*worker_routine)(void*)) From 4a122b57a048bc63c85896e184ebce445b97c03e Mon Sep 17 00:00:00 2001 From: Andrey Malets Date: Mon, 22 Jan 2018 18:38:52 +0500 Subject: [PATCH 2/2] Add and use a define to check if pthread_cancel is available. --- configure.ac | 1 + src/sb_thread.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 371995a..86c4280 100644 --- a/configure.ac +++ b/configure.ac @@ -340,6 +340,7 @@ isatty \ memalign \ memset \ posix_memalign \ +pthread_cancel \ pthread_yield \ setvbuf \ sqrt \ diff --git a/src/sb_thread.c b/src/sb_thread.c index f37aafd..cd868e7 100644 --- a/src/sb_thread.c +++ b/src/sb_thread.c @@ -33,7 +33,9 @@ # include #endif +#ifndef HAVE_PTHREAD_CANCEL #include +#endif #include "sb_thread.h" #include "sb_rand.h" @@ -86,6 +88,9 @@ void sb_thread_done(void) free(threads); } +#ifndef HAVE_PTHREAD_CANCEL +#define PTHREAD_CANCELED ((void *) -1) + struct sb_thread_proxy { void *(*start_routine) (void *); void *arg; @@ -95,9 +100,6 @@ static int thread_cancel_signal = SIGUSR1; static void thread_cancel_handler(int sig) { -#ifndef PTHREAD_CANCELED -# define PTHREAD_CANCELED ((void *) -1) -#endif if (sig == thread_cancel_signal) pthread_exit(PTHREAD_CANCELED); } @@ -119,10 +121,14 @@ static void* thread_start_routine_proxy(void *arg) { install_thread_signal_handler(); return start_routine(real_arg); } +#endif int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { +#ifdef HAVE_PTHREAD_CANCEL + return pthread_create(thread, attr, start_routine, arg); +#else struct sb_thread_proxy *proxy = malloc(sizeof(struct sb_thread_proxy)); if (!proxy) { @@ -136,6 +142,7 @@ int sb_thread_create(pthread_t *thread, const pthread_attr_t *attr, free(proxy); } return rv; +#endif } int sb_thread_join(pthread_t thread, void **retval) @@ -145,7 +152,11 @@ int sb_thread_join(pthread_t thread, void **retval) int sb_thread_cancel(pthread_t thread) { +#ifdef HAVE_PTHREAD_CANCEL + return pthread_cancel(thread); +#else return pthread_kill(thread, thread_cancel_signal); +#endif } int sb_thread_create_workers(void *(*worker_routine)(void*))