Skip to content

Commit

Permalink
Alloc connections pools in the NULL ctx
Browse files Browse the repository at this point in the history
  • Loading branch information
arr2036 committed Jun 20, 2014
1 parent 9990029 commit 9652cc6
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/include/libradius.h
Expand Up @@ -647,7 +647,7 @@ void fr_printf_log(char const *, ...) CC_HINT(format (printf, 1, 2));
* Several handy miscellaneous functions.
*/
int fr_set_signal(int sig, sig_t func);
TALLOC_CTX *fr_autofree_ctx(void);
int fr_link_talloc_ctx_free(TALLOC_CTX *parent, TALLOC_CTX *child);
char const *fr_inet_ntop(int af, void const *src);
char const *ip_ntoa(char *, uint32_t);
int fr_pton4(fr_ipaddr_t *out, char const *value, size_t inlen, bool resolve, bool fallback);
Expand Down
7 changes: 1 addition & 6 deletions src/lib/debug.c
Expand Up @@ -215,12 +215,7 @@ fr_bt_marker_t *fr_backtrace_attach(fr_cbuff_t **cbuff, TALLOC_CTX *obj)
if (*cbuff == NULL) {
PTHREAD_MUTEX_LOCK(&fr_debug_init);
/* Check again now we hold the mutex - eww*/
if (*cbuff == NULL) {
TALLOC_CTX *ctx;

ctx = fr_autofree_ctx();
*cbuff = fr_cbuff_alloc(ctx, MAX_BT_CBUFF, true);
}
if (*cbuff == NULL) *cbuff = fr_cbuff_alloc(NULL, MAX_BT_CBUFF, true);
PTHREAD_MUTEX_UNLOCK(&fr_debug_init);
}

Expand Down
55 changes: 42 additions & 13 deletions src/lib/misc.c
Expand Up @@ -35,7 +35,6 @@ RCSID("$Id$")
} while (0)

#ifdef HAVE_PTHREAD_H
static pthread_mutex_t autofree_context = PTHREAD_MUTEX_INITIALIZER;
# define PTHREAD_MUTEX_LOCK pthread_mutex_lock
# define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
#else
Expand All @@ -53,6 +52,11 @@ static char const *months[] = {

fr_thread_local_setup(char *, fr_inet_ntop_buffer); /* macro */

typedef struct fr_talloc_link {
bool armed;
TALLOC_CTX *child;
} fr_talloc_link_t;

/** Sets a signal handler using sigaction if available, else signal
*
* @param sig to set handler for.
Expand Down Expand Up @@ -81,25 +85,50 @@ int fr_set_signal(int sig, sig_t func)
return 0;
}

/** Allocates a new talloc context from the root autofree context
static int _fr_trigger_talloc_ctx_free(fr_talloc_link_t *trigger)
{
if (trigger->armed) talloc_free(trigger->child);

return 0;
}

static int _fr_disarm_talloc_ctx_free(bool **armed)
{
**armed = false;
return 0;
}

/** Link a parent and a child context, so the child is freed before the parent
*
* This function is threadsafe, whereas using the NULL context is not.
* @note This is not thread safe. Do not free parent before threads are joined, do not call from a child thread.
* @note It's OK to free the child before threads are joined, but this will leak memory until the parent is freed.
*
* @note The returned context must be freed by the caller.
* @returns a new talloc context parented by the root autofree context.
* @param parent who's fate the child should share.
* @param child bound to parent's lifecycle.
* @return 0 on success -1 on failure.
*/
TALLOC_CTX *fr_autofree_ctx(void)
int fr_link_talloc_ctx_free(TALLOC_CTX *parent, TALLOC_CTX *child)
{
static TALLOC_CTX *ctx = NULL, *child;
PTHREAD_MUTEX_LOCK(&autofree_context);
if (!ctx) {
ctx = talloc_autofree_context();
fr_talloc_link_t *trigger;
bool **disarm;

trigger = talloc(parent, fr_talloc_link_t);
if (!trigger) return -1;

disarm = talloc(child, bool *);
if (!disarm) {
talloc_free(trigger);
return -1;
}

child = talloc_new(ctx);
PTHREAD_MUTEX_UNLOCK(&autofree_context);
trigger->child = child;
trigger->armed = true;
*disarm = &trigger->armed;

talloc_set_destructor(trigger, _fr_trigger_talloc_ctx_free);
talloc_set_destructor(disarm, _fr_disarm_talloc_ctx_free);

return child;
return 0;
}

/*
Expand Down
20 changes: 15 additions & 5 deletions src/main/connection.c
Expand Up @@ -587,13 +587,23 @@ fr_connection_pool_t *fr_connection_pool_init(CONF_SECTION *parent,
cs = cf_section_sub_find(parent, "pool");
if (!cs) cs = cf_section_sub_find(parent, "limit");

if (cs) {
pool = talloc_zero(cs, fr_connection_pool_t);
} else {
pool = talloc_zero(parent, fr_connection_pool_t);
}
/*
* Pool is allocated in the NULL context as
* threads are likely to allocate memory
* beneath the pool.
*/
pool = talloc_zero(NULL, fr_connection_pool_t);
if (!pool) return NULL;

/*
* Ensure the pool is freed at the same time
* as its parent.
*/
if (fr_link_talloc_ctx_free(cs ? cs : parent, pool) < 0) {
talloc_free(pool);
return NULL;
}

pool->cs = cs;
pool->ctx = ctx;
pool->create = c;
Expand Down

0 comments on commit 9652cc6

Please sign in to comment.