From: Alan T. DeKok Date: Wed, 2 Sep 2015 19:41:48 +0000 (-0400) Subject: On HUP, reload a module which has changed X-Git-Tag: release_3_0_10~175 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dd2594b3ce45c4b6e3d8c57523ab8acfeffc2452;p=thirdparty%2Ffreeradius-server.git On HUP, reload a module which has changed --- diff --git a/src/include/conffile.h b/src/include/conffile.h index 3ca330f260c..62d16b028d4 100644 --- a/src/include/conffile.h +++ b/src/include/conffile.h @@ -292,7 +292,7 @@ CONF_ITEM *cf_reference_item(CONF_SECTION const *parentcs, #define CF_FILE_ERROR (1) #define CF_FILE_CONFIG (1 << 2) #define CF_FILE_MODULE (1 << 3) -int cf_file_changed(CONF_SECTION *cs); +int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback); extern CONF_SECTION *root_config; extern bool cf_new_escape; diff --git a/src/main/conffile.c b/src/main/conffile.c index cad30b4191c..855c0bb32ab 100644 --- a/src/main/conffile.c +++ b/src/main/conffile.c @@ -412,20 +412,27 @@ static bool cf_file_input(CONF_SECTION *cs, char const *filename) } +typedef struct cf_file_callback_t { + int rcode; + rb_walker_t callback; + CONF_SECTION *modules; +} cf_file_callback_t; + + /* * Return 0 for keep going, 1 for stop. */ static int file_callback(void *ctx, void *data) { - int *rcode = ctx; - struct stat buf; + cf_file_callback_t *cb = ctx; cf_file_t *file = data; + struct stat buf; /* * The file doesn't exist or we can no longer read it. */ if (stat(file->filename, &buf) < 0) { - *rcode = CF_FILE_ERROR; + cb->rcode = CF_FILE_ERROR; return 1; } @@ -434,9 +441,10 @@ static int file_callback(void *ctx, void *data) */ if (buf.st_mtime != file->buf.st_mtime) { if (!file->input) { - *rcode |= CF_FILE_CONFIG; + cb->rcode |= CF_FILE_CONFIG; } else { - *rcode |= CF_FILE_MODULE; + (void) cb->callback(cb->modules, file->cs); + cb->rcode |= CF_FILE_MODULE; } } @@ -447,11 +455,11 @@ static int file_callback(void *ctx, void *data) /* * See if any of the files have changed. */ -int cf_file_changed(CONF_SECTION *cs) +int cf_file_changed(CONF_SECTION *cs, rb_walker_t callback) { - int rcode; CONF_DATA *cd; CONF_SECTION *top; + cf_file_callback_t cb; rbtree_t *tree; top = cf_top_section(cs); @@ -460,10 +468,13 @@ int cf_file_changed(CONF_SECTION *cs) tree = cd->data; - rcode = CF_FILE_NONE; - (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &rcode); + cb.rcode = CF_FILE_NONE; + cb.callback = callback; + cb.modules = cf_section_sub_find(cs, "modules"); - return rcode; + (void) rbtree_walk(tree, RBTREE_IN_ORDER, file_callback, &cb); + + return cb.rcode; } static int _cf_section_free(CONF_SECTION *cs) diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index fd6881d70a1..550e025579b 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -25,6 +25,7 @@ RCSID("$Id$") #include #include +#include #include #include @@ -1081,6 +1082,43 @@ void hup_logfile(void) } } +static int hup_callback(void *ctx, void *data) +{ + CONF_SECTION *modules = ctx; + CONF_SECTION *cs = data; + CONF_SECTION *parent; + char const *name; + module_instance_t *mi; + + /* + * Files may be defined in sub-sections of a module + * config. Walk up the tree until we find the module + * definition. + */ + parent = cf_item_parent(cf_section_to_item(cs)); + while (parent != modules) { + cs = parent; + parent = cf_item_parent(cf_section_to_item(cs)); + + /* + * Something went wrong. Oh well... + */ + if (!parent) return 0; + } + + name = cf_section_name2(cs); + if (!name) name = cf_section_name1(cs); + + mi = module_find(modules, name); + if (!mi) return 0; + + if ((mi->entry->module->type & RLM_TYPE_HUP_SAFE) == 0) return 0; + + if (!module_hup_module(mi->cs, mi, time(NULL))) return 0; + + return 0; +} + void main_config_hup(void) { int rcode; @@ -1110,7 +1148,7 @@ void main_config_hup(void) } last_hup = when; - rcode = cf_file_changed(cs_cache->cs); + rcode = cf_file_changed(cs_cache->cs, hup_callback); if (rcode == CF_FILE_NONE) { INFO("HUP - No files changed. Ignoring"); return;