};
typedef struct {
- void *(*func)(void *);
- void *arg;
+ void *(*func)(void *);
+ void *arg;
} fr_schedule_entry_point_t;
static _Thread_local int worker_id; //!< Internal ID of the current worker thread.
{
fr_schedule_entry_point_t *ep = arg;
sigset_t sig_mask; /* signals to block */
+ void *ret;
/*
* We generally use kqueue to signal threads so we
sigfillset(&sig_mask);
if (pthread_sigmask(SIG_BLOCK, &sig_mask, NULL) != 0) {
- fr_strerror_printf("Failed blocking child signals: %s", fr_syserror(errno));
+ free(arg); /* Free memory our parent allocated */
return NULL;
}
- return ep->func(ep->arg);
+ ret = ep->func(ep->arg);
+ free(arg); /* Free memory our parent allocated */
+
+ return ret;
}
/** Creates a new thread using our standard set of options
{
pthread_attr_t attr;
int ret;
- fr_schedule_entry_point_t ep = { .func = func, .arg = arg };
+ fr_schedule_entry_point_t *ep;
+
/*
* Set the thread to wait around after it's exited
* so it can be joined. This is more of a useful
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- ret = pthread_create(thread, &attr, schedule_pthread_entry, &ep);
+ ep = malloc(sizeof(fr_schedule_entry_point_t)); /* MUST be malloc - would corrupt NULL ctx */
+ ep->func = func;
+ ep->arg = arg;
+
+ ret = pthread_create(thread, &attr, schedule_pthread_entry, ep);
if (ret != 0) {
+ free(ep);
fr_strerror_printf("Failed creating thread: %s", fr_syserror(ret));
return -1;
}