When we first added tirggers they were mostly generated by individual requests passing through the server, but today more of the connections and management are done independent of requests.
}
}
- trigger_exec(NULL, NULL, NULL, "server.start", false, NULL);
+ trigger_exec(NULL, NULL, "server.start", false, NULL);
/*
* Inform the parent (who should still be waiting) that the rest of
* Fire signal and stop triggers after ignoring SIGTERM, so handlers are
* not killed with the rest of the process group, below.
*/
- if (status == 2) trigger_exec(NULL, NULL, NULL, "server.signal.term", true, NULL);
- trigger_exec(NULL, NULL, NULL, "server.stop", false, NULL);
+ if (status == 2) trigger_exec(NULL, NULL, "server.signal.term", true, NULL);
+ trigger_exec(NULL, NULL, "server.stop", false, NULL);
/*
* Stop the scheduler, this signals the network and worker threads
#define CONN_TRIGGER(_state) do { \
if (conn->pub.triggers) { \
trigger_exec(unlang_interpret_get_thread_default(), \
- NULL, NULL, fr_table_str_by_value(fr_connection_trigger_names, _state, "<INVALID>"), true, NULL); \
+ NULL, fr_table_str_by_value(fr_connection_trigger_names, _state, "<INVALID>"), true, NULL); \
} \
} while (0)
/** Send an exfile trigger.
*
* @param[in] ef to send trigger for.
- * @param[in] request The current request.
* @param[in] entry for the file that the event occurred on.
* @param[in] name_suffix trigger name suffix.
*/
-static inline void exfile_trigger_exec(exfile_t *ef, request_t *request, exfile_entry_t *entry, char const *name_suffix)
+static inline void exfile_trigger_exec(exfile_t *ef, exfile_entry_t *entry, char const *name_suffix)
{
char name[128];
fr_pair_t *vp;
da = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal()), FR_EXFILE_NAME);
if (!da) {
- ROPTIONAL(RERROR, ERROR, "Incomplete internal dictionary: Missing definition for \"Exfile-Name\"");
+ ERROR("Incomplete internal dictionary: Missing definition for \"Exfile-Name\"");
return;
}
- fr_pair_list_copy(request ? request->request_ctx : NULL, &args, &ef->trigger_args);
+ fr_pair_list_copy(NULL, &args, &ef->trigger_args);
fr_dcursor_init(&cursor, &args);
MEM(vp = fr_pair_afrom_da(NULL, da));
fr_dcursor_prepend(&cursor, vp);
snprintf(name, sizeof(name), "%s.%s", ef->trigger_prefix, name_suffix);
- trigger_exec(unlang_interpret_get_thread_default(), request, ef->conf, name, false, &args);
+ trigger_exec(unlang_interpret_get_thread_default(), ef->conf, name, false, &args);
fr_pair_list_free(&args);
}
-static void exfile_cleanup_entry(exfile_t *ef, request_t *request, exfile_entry_t *entry)
+static void exfile_cleanup_entry(exfile_t *ef, exfile_entry_t *entry)
{
if (entry->fd >= 0) close(entry->fd);
/*
* Issue close trigger *after* we've closed the fd
*/
- exfile_trigger_exec(ef, request, entry, "close");
+ exfile_trigger_exec(ef, entry, "close");
/*
* Trigger still needs access to filename to populate Exfile-Name
for (i = 0; i < ef->max_entries; i++) {
if (!ef->entries[i].filename) continue;
- exfile_cleanup_entry(ef, NULL, &ef->entries[i]);
+ exfile_cleanup_entry(ef, &ef->entries[i]);
}
pthread_mutex_unlock(&ef->mutex);
* sure that no other thread is writing to the file.
*
* @param ef The logfile context returned from exfile_init().
- * @param request The current request.
* @param filename the file to open.
* @param permissions to use.
* @return
* - FD used to write to the file.
* - -1 on failure.
*/
-int exfile_open(exfile_t *ef, request_t *request, char const *filename, mode_t permissions)
+int exfile_open(exfile_t *ef, char const *filename, mode_t permissions)
{
int i, tries, unused = -1, found = -1, oldest = -1;
bool do_cleanup = false;
} else if (do_cleanup) {
if ((ef->entries[i].last_used + ef->max_idle) >= now) continue;
- exfile_cleanup_entry(ef, request, &ef->entries[i]);
+ exfile_cleanup_entry(ef, &ef->entries[i]);
}
}
* There are no unused entries, free the oldest one.
*/
if (unused < 0) {
- exfile_cleanup_entry(ef, request, &ef->entries[oldest]);
+ exfile_cleanup_entry(ef, &ef->entries[oldest]);
unused = oldest;
}
ef->entries[i].fd = exfile_open_mkdir(ef, filename, permissions);
if (ef->entries[i].fd < 0) goto error;
- exfile_trigger_exec(ef, request, &ef->entries[i], "open");
+ exfile_trigger_exec(ef, &ef->entries[i], "open");
try_lock:
/*
fr_strerror_printf("Failed to seek in file %s: %s", filename, fr_syserror(errno));
error:
- exfile_cleanup_entry(ef, request, &ef->entries[i]);
+ exfile_cleanup_entry(ef, &ef->entries[i]);
pthread_mutex_unlock(&(ef->mutex));
return -1;
}
*/
ef->entries[i].last_used = now;
- exfile_trigger_exec(ef, request, &ef->entries[i], "reserve");
+ exfile_trigger_exec(ef, &ef->entries[i], "reserve");
/* coverity[missing_unlock] */
return ef->entries[i].fd;
* the file.
*
* @param ef The logfile context returned from #exfile_init.
- * @param request The current request.
* @param fd the FD to close (i.e. return to the pool).
* @return
* - 0 on success.
* - -1 on failure.
*/
-int exfile_close(exfile_t *ef, request_t *request, int fd)
+int exfile_close(exfile_t *ef, int fd)
{
uint32_t i;
(void) rad_unlockfd(ef->entries[i].fd, 0);
pthread_mutex_unlock(&(ef->mutex));
- exfile_trigger_exec(ef, request, &ef->entries[i], "release");
+ exfile_trigger_exec(ef, &ef->entries[i], "release");
return 0;
}
void exfile_enable_triggers(exfile_t *ef, CONF_SECTION *cs, char const *trigger_prefix,
fr_pair_list_t *trigger_args);
-int exfile_open(exfile_t *lf, request_t *request, char const *filename,
- mode_t permissions);
+int exfile_open(exfile_t *lf, char const *filename, mode_t permissions);
-int exfile_close(exfile_t *lf, request_t *request, int fd);
+int exfile_close(exfile_t *lf, int fd);
#ifdef __cplusplus
}
last_hup = when;
- trigger_exec(unlang_interpret_get_thread_default(), NULL, NULL, "server.signal.hup", true, NULL);
+ trigger_exec(unlang_interpret_get_thread_default(), NULL, "server.signal.hup", true, NULL);
fr_event_loop_exit(event_list, 0x80);
}
}
/** Send a connection pool trigger.
*
* @param[in] pool to send trigger for.
- * @param[in] request The current request (may be NULL).
* @param[in] event trigger name suffix.
*/
-static inline void fr_pool_trigger_exec(fr_pool_t *pool, request_t *request, char const *event)
+static inline void fr_pool_trigger_exec(fr_pool_t *pool, char const *event)
{
char name[128];
if (!pool->triggers_enabled) return;
snprintf(name, sizeof(name), "%s.%s", pool->trigger_prefix, event);
- trigger_exec(unlang_interpret_get_thread_default(), request, pool->cs, name, true, &pool->trigger_args);
+ trigger_exec(unlang_interpret_get_thread_default(), pool->cs, name, true, &pool->trigger_args);
}
/** Find a connection handle in the connection list
* Must be done inside the mutex, reconnect callback
* may modify args.
*/
- fr_pool_trigger_exec(pool, request, "fail");
+ fr_pool_trigger_exec(pool, "fail");
pthread_cond_broadcast(&pool->done_spawn);
pthread_mutex_unlock(&pool->mutex);
* Must be done inside the mutex, reconnect callback
* may modify args.
*/
- fr_pool_trigger_exec(pool, request, "open");
+ fr_pool_trigger_exec(pool, "open");
pthread_cond_broadcast(&pool->done_spawn);
if (unlock) pthread_mutex_unlock(&pool->mutex);
* @note Must be called with the mutex held.
*
* @param[in] pool to modify.
- * @param[in] request The current request.
* @param[in] this Connection to delete.
*/
-static void connection_close_internal(fr_pool_t *pool, request_t *request, fr_pool_connection_t *this)
+static void connection_close_internal(fr_pool_t *pool, fr_pool_connection_t *this)
{
/*
* If it's in use, release it.
fr_heap_extract(pool->heap, this);
}
- fr_pool_trigger_exec(pool, request, "close");
+ fr_pool_trigger_exec(pool, "close");
connection_unlink(pool, this);
if (pool->state.num <= pool->min) {
ROPTIONAL(RDEBUG2, DEBUG2, "You probably need to lower \"min\"");
}
- connection_close_internal(pool, request, this);
+ connection_close_internal(pool, this);
return 0;
}
ROPTIONAL(RDEBUG2, DEBUG2, "Closing connection (%" PRIu64 ") as we have too many unused connections",
found->number);
- connection_close_internal(pool, request, found);
+ connection_close_internal(pool, found);
/*
* Decrease the delay for the next time we clean
* Must be done inside the mutex, reconnect callback
* may modify args.
*/
- fr_pool_trigger_exec(pool, request, "none");
+ fr_pool_trigger_exec(pool, "none");
}
return NULL;
}
}
- fr_pool_trigger_exec(pool, NULL, "start");
+ fr_pool_trigger_exec(pool, "start");
return 0;
}
this = fr_heap_peek(pool->heap);
if (!this) break; /* There wasn't 'start' connections available */
- connection_close_internal(pool, request, this);
+ connection_close_internal(pool, this);
}
/*
* Must be done inside the mutex, reconnect callback
* may modify args.
*/
- fr_pool_trigger_exec(pool, request, "reconnect");
+ fr_pool_trigger_exec(pool, "reconnect");
/*
* Allow new spawn attempts, and wakeup any threads
while ((this = pool->head) != NULL) {
INFO("Closing connection (%" PRIu64 ")", this->number);
- connection_close_internal(pool, NULL, this);
+ connection_close_internal(pool, this);
}
- fr_pool_trigger_exec(pool, NULL, "stop");
+ fr_pool_trigger_exec(pool, "stop");
fr_assert(pool->head == NULL);
fr_assert(pool->tail == NULL);
*/
connection_check(pool, request);
- if (trigger_min) fr_pool_trigger_exec(pool, request, "min");
- if (trigger_max) fr_pool_trigger_exec(pool, request, "max");
+ if (trigger_min) fr_pool_trigger_exec(pool, "min");
+ if (trigger_max) fr_pool_trigger_exec(pool, "max");
}
/** Reconnect a suspected inviable connection
ROPTIONAL(RINFO, INFO, "Deleting inviable connection (%" PRIu64 ")", this->number);
- connection_close_internal(pool, request, this);
+ connection_close_internal(pool, this);
connection_check(pool, request); /* Whilst we still have the lock (will release the lock) */
/*
ROPTIONAL(RINFO, INFO, "Deleting connection (%" PRIu64 ")", this->number);
- connection_close_internal(pool, request, this);
+ connection_close_internal(pool, this);
connection_check(pool, request);
return 1;
}
*
* @param[in] intp Interpreter to run the trigger with. If this is NULL the
* trigger will be executed synchronously.
- *
- * @param[in] request The current request.
* @param[in] cs to search for triggers in.
* If cs is not NULL, the portion after the last '.' in name is used for the trigger.
* If cs is NULL, the entire name is used to find the trigger in the global trigger
* - 0 on success.
* - -1 on failure.
*/
-int trigger_exec(unlang_interpret_t *intp, request_t *request,
+int trigger_exec(unlang_interpret_t *intp,
CONF_SECTION const *cs, char const *name, bool rate_limit, fr_pair_list_t *args)
{
CONF_SECTION const *subcs;
char const *attr;
char const *value;
- request_t *child;
+ request_t *request;
fr_trigger_t *trigger;
ssize_t slen;
ci = cf_reference_item(subcs, trigger_exec_main, attr);
if (!ci) {
- ROPTIONAL(RDEBUG2, DEBUG2, "No trigger configured for: %s", attr);
+ DEBUG2("No trigger configured for: %s", attr);
return -1;
}
if (!cf_item_is_pair(ci)) {
- ROPTIONAL(RERROR, ERROR, "Trigger is not a configuration variable: %s", attr);
+ ERROR("Trigger is not a configuration variable: %s", attr);
return -1;
}
value = cf_pair_value(cp);
if (!value) {
- ROPTIONAL(RERROR, ERROR, "Trigger has no value: %s", name);
+ ERROR("Trigger has no value: %s", name);
return -1;
}
/*
* Allocate a request to run asynchronously in the interpreter.
*/
- child = request_alloc_internal(NULL, (&(request_init_args_t){ .parent = request, .detachable = true }));
+ request = request_alloc_internal(NULL, (&(request_init_args_t){ .detachable = true }));
/*
* Add the args to the request data, so they can be picked up by the
* trigger_xlat function.
*/
- if (args && (request_data_add(child, &trigger_exec_main, REQUEST_INDEX_TRIGGER_ARGS, args,
+ if (args && (request_data_add(request, &trigger_exec_main, REQUEST_INDEX_TRIGGER_ARGS, args,
false, false, false) < 0)) {
- talloc_free(child);
+ talloc_free(request);
return -1;
}
memcpy(&name_tmp, &name, sizeof(name_tmp));
- if (request_data_add(child, &trigger_exec_main, REQUEST_INDEX_TRIGGER_NAME,
+ if (request_data_add(request, &trigger_exec_main, REQUEST_INDEX_TRIGGER_NAME,
name_tmp, false, false, false) < 0) {
- talloc_free(child);
+ talloc_free(request);
return -1;
}
}
- MEM(trigger = talloc_zero(child, fr_trigger_t));
+ MEM(trigger = talloc_zero(request, fr_trigger_t));
fr_value_box_list_init(&trigger->args);
trigger->command = talloc_strdup(trigger, value);
trigger->timeout = fr_time_delta_from_sec(5); /* FIXME - Should be configurable? */
- /*
- * Automatically populate the trigger's
- * request list from the parent's.
- */
- if (request && !fr_pair_list_empty(&request->request_pairs)) {
- (void) fr_pair_list_copy(child->request_ctx, &child->request_pairs, &request->request_pairs);
- }
-
slen = xlat_tokenize_argv(trigger, &trigger->xlat, NULL,
&FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1), NULL, NULL);
if (slen <= 0) {
cf_log_err(cp, "%s", trigger->command);
cf_log_err(cp, "%s^ %s", spaces, text);
- talloc_free(child);
+ talloc_free(request);
talloc_free(spaces);
talloc_free(text);
return -1;
* interpreter for the thread.
*/
if (intp) {
- unlang_interpret_set(child, intp);
- if (unlang_subrequest_child_push_and_detach(child) < 0) {
+ unlang_interpret_set(request, intp);
+ if (unlang_subrequest_child_push_and_detach(request) < 0) {
error:
- ROPTIONAL(RPEDEBUG, PERROR, "Running trigger failed");
- talloc_free(child);
+ PERROR("Running trigger failed");
+ talloc_free(request);
return -1;
}
}
- if (unlang_function_push(child, trigger_run, trigger_resume,
+ if (unlang_function_push(request, trigger_run, trigger_resume,
NULL, UNLANG_TOP_FRAME, trigger) < 0) goto error;
if (!intp) {
/*
* Wait for the exec to finish too,
* so where there are global events
- * the child processes don't race
+ * the request processes don't race
* with something like the server
* shutting down.
*/
- unlang_interpret_synchronous(NULL, child);
- talloc_free(child);
+ unlang_interpret_synchronous(NULL, request);
+ talloc_free(request);
}
/*
- * Otherwise the worker cleans up the child request.
+ * Otherwise the worker cleans up the request request.
*/
return 0;
}
int trigger_exec_init(CONF_SECTION const *cs);
int trigger_exec(unlang_interpret_t *intp,
- request_t *request, CONF_SECTION const *cs,
- char const *name, bool quench, fr_pair_list_t *args)
- CC_HINT(nonnull (4));
+ CONF_SECTION const *cs, char const *name, bool quench, fr_pair_list_t *args)
+ CC_HINT(nonnull(3));
void trigger_exec_free(void);
#define CONN_TRIGGER(_state) do { \
if (trunk->pub.triggers) { \
trigger_exec(unlang_interpret_get_thread_default(), \
- NULL, NULL, fr_table_str_by_value(fr_trunk_conn_trigger_names, _state, \
- "<INVALID>"), true, NULL); \
+ NULL, fr_table_str_by_value(fr_trunk_conn_trigger_names, _state, \
+ "<INVALID>"), true, NULL); \
} \
} while (0)
#define REQUEST_TRIGGER(_state) do { \
if (trunk->pub.triggers) { \
trigger_exec(unlang_interpret_get_thread_default(), \
- NULL, NULL, fr_table_str_by_value(fr_trunk_req_trigger_names, _state, \
- "<INVALID>"), true, NULL); \
+ NULL, fr_table_str_by_value(fr_trunk_req_trigger_names, _state, \
+ "<INVALID>"), true, NULL); \
} \
} while (0)
bfd_request(session, request, &packet);
- trigger_exec(unlang_interpret_get_thread_default(), request, NULL, buffer, false, NULL);
+ trigger_exec(unlang_interpret_get_thread_default(), NULL, buffer, false, NULL);
}
bfd_request(session, &request, &packet);
- trigger_exec(unlang_interpret_get_thread_default(), &request, NULL, "server.bfd.warn", false, NULL);
+ trigger_exec(unlang_interpret_get_thread_default(), NULL, "server.bfd.warn", false, NULL);
}
RDEBUG2("%s expands to %s", inst->filename, buffer);
- outfd = exfile_open(inst->ef, request, buffer, inst->perm);
+ outfd = exfile_open(inst->ef, buffer, inst->perm);
if (outfd < 0) {
RPERROR("Couldn't open file %s", buffer);
/* coverity[missing_unlock] */
RERROR("Couldn't open file %s: %s", buffer, fr_syserror(errno));
fail:
if (outfp) fclose(outfp);
- exfile_close(inst->ef, request, outfd);
+ exfile_close(inst->ef, outfd);
RETURN_MODULE_FAIL;
}
* Flush everything
*/
fclose(outfp);
- exfile_close(inst->ef, request, outfd);
+ exfile_close(inst->ef, outfd);
/*
* And everything is fine.
*p = '/';
}
- fd = exfile_open(inst->file.ef, request, path, inst->file.permissions);
+ fd = exfile_open(inst->file.ef, path, inst->file.permissions);
if (fd < 0) {
RERROR("Failed to open %s: %s", path, fr_syserror(errno));
rcode = RLM_MODULE_FAIL;
if (writev(fd, vector_p, vector_len) < 0) {
RERROR("Failed writing to \"%s\": %s", path, fr_syserror(errno));
- exfile_close(inst->file.ef, request, fd);
+ exfile_close(inst->file.ef, fd);
/* Assert on the extra fatal errors */
fr_assert((errno != EINVAL) && (errno != EFAULT));
RETURN_MODULE_FAIL;
}
- exfile_close(inst->file.ef, request, fd);
+ exfile_close(inst->file.ef, fd);
}
break;
return;
}
- fd = exfile_open(inst->ef, request, filename, 0640);
+ fd = exfile_open(inst->ef, filename, 0640);
if (fd < 0) {
ERROR("Couldn't open logfile '%s': %s", expanded, fr_syserror(errno));
if (failed) ERROR("Failed writing to logfile '%s': %s", expanded, fr_syserror(errno));
talloc_free(expanded);
- exfile_close(inst->ef, request, fd);
+ exfile_close(inst->ef, fd);
}
MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_BOOL, NULL, false));
fr_dcursor_append(out, vb);
- if (trigger_exec(unlang_interpret_get(request), request, NULL, in_head->vb_strvalue, false, NULL) < 0) {
+ if (trigger_exec(unlang_interpret_get(request), NULL, in_head->vb_strvalue, false, NULL) < 0) {
RPEDEBUG("Running trigger failed");
vb->vb_bool = false;
return XLAT_ACTION_FAIL;