Merge pull request #206 from andrey-malets/avoid-pthread-cancel

Avoid pthread_cancel as it may not be defined.
This commit is contained in:
Alexey Kopytov
2018-01-22 17:13:09 +03:00
committed by GitHub
2 changed files with 60 additions and 0 deletions

View File

@ -340,6 +340,7 @@ isatty \
memalign \
memset \
posix_memalign \
pthread_cancel \
pthread_yield \
setvbuf \
sqrt \

View File

@ -33,6 +33,10 @@
# include <pthread.h>
#endif
#ifndef HAVE_PTHREAD_CANCEL
#include <signal.h>
#endif
#include "sb_thread.h"
#include "sb_rand.h"
#include "sb_logger.h"
@ -84,10 +88,61 @@ 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;
};
static int thread_cancel_signal = SIGUSR1;
static void thread_cancel_handler(int sig)
{
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);
}
#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)
{
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;
#endif
}
int sb_thread_join(pthread_t thread, void **retval)
@ -97,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*))