/*
* Create and initialize the new request.
*/
- request = request_local_alloc(ctx, NULL);
+ request = request_local_alloc_external(ctx, NULL);
/*
* FIXME - Should be less RADIUS centric, but everything
* else assumes RADIUS at the moment so we can fix this later.
char *p;
char input[8192];
char output[8192];
- request_t *request;
+ request_t *request;
/*
* Create and initialize the new request.
*/
- request = request_alloc(NULL, NULL);
+ request = request_alloc_external(NULL, NULL);
request->log.dst = talloc_zero(request, log_dst_t);
request->log.dst->func = vlog_request;
{
request_t *request;
- request = request_alloc(NULL, NULL);
+ request = request_alloc_external(NULL, NULL);
if (!request) return NULL;
if (!request->packet) request->packet = fr_radius_packet_alloc(request, false);
(chbind->response == NULL));
/* Set-up the fake request */
- fake = request_alloc(request, &(request_init_args_t){ .parent = request });
+ fake = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
MEM(fr_pair_prepend_by_da(fake->request_ctx, &vp, &fake->request_pairs, attr_freeradius_proxied_to) >= 0);
fr_pair_value_from_str(vp, "127.0.0.1", sizeof("127.0.0.1"), '\0', false);
uint32_t priority; //!< higher == higher priority
};
-#define request_is_external(_x) (_x->async && (_x->async->listen != NULL))
-#define request_is_internal(_x) (!request_is_external(_x))
-
int fr_io_listen_free(fr_listen_t *li);
*
* @param[in] request_p Pointer to the request to cancel.
* Will be set to NULL.
- * @param[in] now The current time.
*/
-static void worker_stop_request(request_t **request_p, fr_time_t now)
+static void worker_stop_request(request_t **request_p)
{
- if ((*request_p)->async->tracking.state == FR_TIME_TRACKING_YIELDED) {
- fr_time_tracking_resume(&(*request_p)->async->tracking, now);
- }
-
/*
* Also marks the request as done and runs
* the internal/external callbacs.
* Waiting too long, delete it.
*/
REDEBUG("Request has reached max_request_time - signalling it to stop");
- worker_stop_request(&request, now);
+ worker_stop_request(&request);
}
/*
if (fr_heap_num_elements(worker->time_order) >= (uint32_t) worker->config.max_requests) goto nak;
- ctx = request = request_alloc(NULL, NULL);
+ ctx = request = request_alloc_external(NULL, NULL);
if (!request) goto nak;
worker_request_init(worker, request, now);
*/
RWARN("Got conflicting packet for request (%" PRIu64 "), telling old request to stop", old->number);
- worker_stop_request(&old, now);
+ worker_stop_request(&old);
worker->stats.dropped++;
insert_new:
{
int i, count;
request_t *request;
- fr_time_t now = fr_time();
// WORKER_VERIFY;
DEBUG("Worker is exiting - telling request %s to stop", request->name);
count++;
}
- worker_stop_request(&request, now);
+ worker_stop_request(&request);
}
fr_assert(fr_heap_num_elements(worker->runnable) == 0);
*/
static void _worker_request_internal_init(request_t *request, void *uctx)
{
+ fr_worker_t *worker = talloc_get_type_abort(uctx, fr_worker_t);
fr_time_t now = fr_time();
- fr_worker_t *worker = uctx;
worker_request_init(worker, request, now);
worker_request_time_tracking_start(worker, request, now);
}
-/** Internal request (i.e. one generated by the interpreter) is now complete
- *
- * Whatever generated the request is now responsible for freeing it.
- */
-static void _worker_request_internal_done(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
-{
- fr_time_t now = fr_time();
- fr_worker_t *worker = uctx;
-
- worker_request_time_tracking_end(worker, request, now);
-
- fr_assert(!fr_heap_entry_inserted(request->runnable_id));
- fr_assert(!fr_heap_entry_inserted(request->time_order_id));
-
- /*
- * Detached requests have to be freed by us
- * as nothing else can free them.
- *
- * All other requests must be freed by the
- * code which allocated them.
- */
- if (!request->parent) talloc_free(request);
-}
/** External request is now complete
*
*/
-static void _worker_request_external_done(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
+static void _worker_request_done_external(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
{
- fr_worker_t *worker = uctx;
+ fr_worker_t *worker = talloc_get_type_abort(uctx, fr_worker_t);
/*
* All external requests MUST have a listener.
*/
+ fr_assert(request_is_external(request));
fr_assert(request->async->listen != NULL);
/*
talloc_free(request);
}
+/** Internal request (i.e. one generated by the interpreter) is now complete
+ *
+ * Whatever generated the request is now responsible for freeing it.
+ */
+static void _worker_request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, void *uctx)
+{
+ fr_worker_t *worker = talloc_get_type_abort(uctx, fr_worker_t);
+
+ worker_request_time_tracking_end(worker, request, fr_time());
+
+ fr_assert(!fr_heap_entry_inserted(request->runnable_id));
+ fr_assert(!fr_heap_entry_inserted(request->time_order_id));
+}
+
+/** Detached request (i.e. one generated by the interpreter with no parent) is now complete
+ *
+ * As the request has no parent, then there's nothing to free it
+ * so we have to.
+ */
+static void _worker_request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
+{
+ /*
+ * No time tracking for detached requests
+ * so we don't need to call
+ * worker_request_time_tracking_end.
+ */
+ fr_assert(!fr_heap_entry_inserted(request->runnable_id));
+ fr_assert(!fr_heap_entry_inserted(request->time_order_id));
+
+ /*
+ * Detached requests have to be freed by us
+ * as nothing else can free them.
+ *
+ * All other requests must be freed by the
+ * code which allocated them.
+ */
+ talloc_free(request);
+}
+
+
+/** Make us responsible for running the request
+ *
+ */
+static void _worker_request_detach(request_t *request, void *uctx)
+{
+ fr_worker_t *worker = talloc_get_type_abort(uctx, fr_worker_t);
+
+ RDEBUG3("Request is detached");
+ fr_assert(request_is_detached(request));
+
+ /*
+ * End the time tracking... We don't track detached requests,
+ * because they don't contribute for the time consumed by an
+ * external request.
+ */
+ worker_request_time_tracking_end(worker, request, fr_time());
+
+ return;
+}
+
+/** This is called by the interpreter when it wants to stop a request
+ *
+ * The idea is to get the request into the same state it would be in
+ * if the interpreter had just finished with it.
+ */
+static void _worker_request_stop(request_t *request, void *uctx)
+{
+ fr_worker_t *worker = talloc_get_type_abort(uctx, fr_worker_t);
+
+ RDEBUG3("Cleaning up request execution state");
+
+ /*
+ * Make sure time tracking is always in a
+ * consistent state when we mark the request
+ * as done.
+ */
+ if (request->async->tracking.state == FR_TIME_TRACKING_YIELDED) {
+ fr_time_tracking_resume(&request->async->tracking, fr_time());
+ }
+
+ /*
+ * If the request is in the runnable queue
+ * yank it back out, so it's not "runnable"
+ * when we call request done.
+ */
+ if (fr_heap_entry_inserted(worker->runnable)) fr_heap_extract(worker->runnable, request);
+}
+
/** Request is now runnable
*
*/
* just stop the request and free it.
*/
if (request->async->channel && !fr_channel_active(request->async->channel)) {
- worker_stop_request(&request, now);
+ worker_stop_request(&request);
return;
}
worker->intp = unlang_interpret_init(worker, el,
&(unlang_request_func_t){
.init_internal = _worker_request_internal_init,
- .done_internal = _worker_request_internal_done,
- .done_external = _worker_request_external_done,
- .mark_runnable = _worker_request_runnable,
+
+ .done_external = _worker_request_done_external,
+ .done_internal = _worker_request_done_internal,
+ .done_detached = _worker_request_done_detached,
+
+ .detach = _worker_request_detach,
+ .stop = _worker_request_stop,
.yield = _worker_request_yield,
.resume = _worker_request_resume,
+ .mark_runnable = _worker_request_runnable,
+
.scheduled = _worker_request_scheduled
},
worker);
/*
* Create and initialize the new request.
*/
- request = request_local_alloc(autofree, NULL);
+ request = request_local_alloc_external(autofree, NULL);
request->packet = fr_radius_packet_alloc(request, false);
TEST_CHECK(request->packet != NULL);
static inline CC_HINT(always_inline) int request_child_init(request_t *child, request_t *parent)
{
child->number = parent->child_number++;
+ if (!child->dict) child->dict = parent->dict;
if ((parent->seq_start == 0) || (parent->number == parent->seq_start)) {
child->name = talloc_typed_asprintf(child, "%s.%" PRIu64, parent->name, child->number);
}
child->seq_start = 0; /* children always start with their own sequence */
child->parent = parent;
- child->dict = parent->dict;
- child->client = parent->client;
/*
* For new server support.
return -1;
}
- /*
- * Fill in the child request.
- */
- child->packet->socket = parent->packet->socket;
- child->packet->socket.inet.dst_port = 0;
- child->packet->socket.fd = -1;
-
- /*
- * This isn't STRICTLY required, as the child request MUST NEVER
- * be put into the request list. However, it's still reasonable
- * practice.
- */
- child->packet->id = child->number & 0xff;
- child->packet->code = parent->packet->code;
- child->packet->timestamp = parent->packet->timestamp;
-
- /*
- * Fill in the child reply, based on the child request.
- */
- fr_socket_addr_swap(&child->reply->socket, &child->packet->socket);
- child->reply->id = child->packet->id;
- child->reply->code = 0; /* UNKNOWN code */
- child->reply->socket.fd = -1;
-
return 0;
}
* @param[in] file the request was allocated in.
* @param[in] line the request was allocated on.
* @param[in] request to (re)-initialise.
+ * @param[in] type of request to initialise.
+ * @param[in] args Other optional arguments.
*/
static inline CC_HINT(always_inline) int request_init(char const *file, int line,
- request_t *request, request_init_args_t const *args)
+ request_t *request, request_type_t type,
+ request_init_args_t const *args)
{
+ /*
+ * Sanity checks for different requests types
+ */
+ switch (type) {
+ case REQUEST_TYPE_EXTERNAL:
+ if (!fr_cond_assert_msg(!args->parent, "External requests must NOT have a parent")) return -1;
+ break;
+
+ case REQUEST_TYPE_INTERNAL:
+ if (!fr_cond_assert_msg(args->parent,
+ "Internal requests must have a parent (args->parent == NULL)")) return -1;
+ break;
+
+ case REQUEST_TYPE_DETACHED:
+ fr_assert_fail("Detached requests should start as type == REQUEST_TYPE_INTERNAL, "
+ "args->detachable and be detached later");
+ return -1;
+ }
+
*request = (request_t){
#ifndef NDEBUG
.magic = REQUEST_MAGIC,
#endif
+ .type = type,
.master_state = REQUEST_ACTIVE,
.dict = args->namespace,
.component = "<pre-core>",
+ .flags = {
+ .detachable = args->detachable
+ },
.runnable_id = -1,
.time_order_id = -1,
+
.alloc_file = file,
.alloc_line = line
};
+
/*
* Initialise the stack
*/
* @param[in] file where the request was allocated.
* @param[in] line where the request was allocated.
* @param[in] ctx to bind the request to.
+ * @param[in] type what type of request to alloc.
* @param[in] args Optional arguments.
* @return
* - A request on success.
* - NULL on error.
*/
-request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args)
+request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx,
+ request_type_t type, request_init_args_t const *args)
{
request_t *request;
fr_dlist_head_t *free_list;
fr_dlist_remove(free_list, request);
}
- if (request_init(file, line, request, args) < 0) {
+ if (request_init(file, line, request, type, args) < 0) {
talloc_free(request);
return NULL;
}
* which needs to be outside of the normal free list, so that it can be freed
* when the module requires, not when the thread destructor runs.
*/
-request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args)
+request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx,
+ request_type_t type, request_init_args_t const *args)
{
request_t *request;
if (!args) args = &default_args;
request = request_alloc_pool(ctx);
- if (request_init(file, line, request, args) < 0) return NULL;
+ if (request_init(file, line, request, type, args) < 0) return NULL;
talloc_set_destructor(request, _request_local_free);
fr_pair_t *state; //!< Pair containing the state list.
} request_pair_lists_t;
+typedef enum {
+ REQUEST_TYPE_EXTERNAL = 0, //!< A request received on the wire.
+ REQUEST_TYPE_INTERNAL, //!< A request generated internally.
+ REQUEST_TYPE_DETACHED //!< A request that was generated internally, but is now detached
+ ///< (not associated with a parent request.)
+} request_type_t;
+
+#define request_is_external(_x) ((_x)->type == REQUEST_TYPE_EXTERNAL)
+#define request_is_internal(_x) ((_x)->type == REQUEST_TYPE_INTERNAL)
+#define request_is_detached(_x) ((_x)->type == REQUEST_TYPE_DETACHED)
+#define request_is_detachable(_x) ((_x)->flags.detachable == 1)
+
struct request_s {
#ifndef NDEBUG
uint32_t magic; //!< Magic number used to detect memory corruption,
#endif
void *stack; //!< unlang interpreter stack.
+ request_type_t type; //!< What type of request this is.
+
request_t *parent; //!< Request that generated this request.
uint64_t number; //!< Monotonically increasing request number. Reset on server restart.
*/
request_pair_lists_t pair_list; //!< Structure containing all pair lists.
- fr_dlist_head_t data; //!< Request metadata.
+ fr_dlist_head_t data; //!< Request data.
+
+ /** Capabilities flags for this request
+ *
+ */
+ struct {
+ uint8_t detachable : 1; //!< This request may be detached from its parent..
+ } flags;
/** Logging information
*
#define RAD_REQUEST_OPTION_CTX (1 << 1)
#define RAD_REQUEST_OPTION_DETAIL (1 << 2)
-/** Allocate a new request
+/** Allocate a new external request
+ *
+ * Use for requests produced by listeners
+ *
+ * @param[in] _ctx Talloc ctx to bind the request to.
+ * @param[in] _args Optional arguments that control how the request is initialised.
+ */
+#define request_alloc_external(_ctx, _args) \
+ _request_alloc( __FILE__, __LINE__, (_ctx), REQUEST_TYPE_EXTERNAL, (_args))
+
+/** Allocate a new internal request
+ *
+ * Use for requests produced by modules and unlang
*
* @param[in] _ctx Talloc ctx to bind the request to.
* @param[in] _args Optional arguments that control how the request is initialised.
*/
-#define request_alloc(_ctx, _args) _request_alloc( __FILE__, __LINE__, (_ctx), (_args))
-request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args);
+#define request_alloc_internal(_ctx, _args) \
+ _request_alloc( __FILE__, __LINE__, (_ctx), REQUEST_TYPE_INTERNAL, (_args))
+
+request_t *_request_alloc(char const *file, int line, TALLOC_CTX *ctx,
+ request_type_t type, request_init_args_t const *args);
-/** Allocate a new request outside of the request pool
+/** Allocate a new external request outside of the request pool
*
* @param[in] _ctx Talloc ctx to allocate the request in.
* @param[in] _args Optional arguments that control how the request is initialised.
*/
-#define request_local_alloc(_ctx, _args) _request_local_alloc(__FILE__, __LINE__, (_ctx), (_args))
-request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx, request_init_args_t const *args);
+#define request_local_alloc_external(_ctx, _args) \
+ _request_local_alloc(__FILE__, __LINE__, (_ctx), REQUEST_TYPE_EXTERNAL, (_args))
+
+/** Allocate a new internal request outside of the request pool
+ *
+ * @param[in] _ctx Talloc ctx to allocate the request in.
+ * @param[in] _args Optional arguments that control how the request is initialised.
+ */
+#define request_local_alloc_internal(_ctx, _args) \
+ _request_local_alloc(__FILE__, __LINE__, (_ctx), REQUEST_TYPE_INTERNAL, (_args))
+
+request_t *_request_local_alloc(char const *file, int line, TALLOC_CTX *ctx,
+ request_type_t type, request_init_args_t const *args);
int request_detach(request_t *child);
/*
* radius_exec_program always needs a request.
*/
- child = request_alloc(NULL, (&(request_init_args_t){ .parent = request, .detachable = true }));
+ child = request_alloc_internal(NULL, (&(request_init_args_t){ .parent = request, .detachable = true }));
/*
* Add the args to the request data, so they can be picked up by the
return NULL;
}
- request = request_alloc(session, NULL);
+ request = request_alloc_internal(session, NULL);
fr_tls_session_request_bind(request, session->ssl);
stack->depth = depth; /* Reset */
}
+/** Indicate to the caller of the interpreter that this request is complete
+ *
+ */
+void unlang_interpret_request_done(request_t *request)
+{
+ unlang_stack_t *stack = request->stack;
+ unlang_interpret_t *intp;
+
+ if (!fr_cond_assert(stack != NULL)) return;
+
+ intp = stack->intp;
+
+ switch (request->type) {
+ case REQUEST_TYPE_EXTERNAL:
+ intp->funcs.done_external(request, stack->result, intp->uctx);
+ break;
+
+ case REQUEST_TYPE_INTERNAL:
+ intp->funcs.done_internal(request, stack->result, intp->uctx);
+ break;
+
+ case REQUEST_TYPE_DETACHED:
+ intp->funcs.done_detached(request, stack->result, intp->uctx);
+ break;
+ }
+}
+
+static inline CC_HINT(always_inline)
+void unlang_interpret_request_stop(request_t *request)
+{
+ unlang_stack_t *stack = request->stack;
+ unlang_interpret_t *intp;
+
+ if (!fr_cond_assert(stack != NULL)) return;
+
+ intp = stack->intp;
+ intp->funcs.stop(request, intp->uctx);
+}
+
+static inline CC_HINT(always_inline)
+void unlang_interpret_request_detach(request_t *request)
+{
+ unlang_stack_t *stack = request->stack;
+ unlang_interpret_t *intp;
+
+ if (!fr_cond_assert(stack != NULL)) return;
+
+ intp = stack->intp;
+ intp->funcs.detach(request, intp->uctx);
+}
+
/** Send a signal (usually stop) to a request
*
* This is typically called via an "async" action, i.e. an action
{
unlang_stack_t *stack = request->stack;
+ switch (action) {
/*
* If we're stopping, then mark the request as stopped.
* Then, call the frame signal handler.
*/
- if (action == FR_SIGNAL_CANCEL) request->master_state = REQUEST_STOP_PROCESSING;
+ case FR_SIGNAL_CANCEL:
+ request->master_state = REQUEST_STOP_PROCESSING;
+ break;
+
+ case FR_SIGNAL_DETACH:
+ /*
+ * Ensure the request is able to be detached
+ * else don't signal.
+ */
+ if (!fr_cond_assert(request_is_detachable(request))) return;
+ break;
+
+ default:
+ break;
+ }
/*
* Requests that haven't been run through the interpret
*/
if (stack && (stack->depth > 0)) frame_signal(request, action, 0);
- if (action == FR_SIGNAL_CANCEL) unlang_interpret_request_done(request);
+ switch (action) {
+ case FR_SIGNAL_CANCEL:
+ unlang_interpret_request_stop(request); /* Stop gets the request in a consistent state */
+ unlang_interpret_request_done(request); /* Done signals the request is complete */
+ break;
+
+ case FR_SIGNAL_DETACH:
+ unlang_interpret_request_detach(request); /* Tell our caller that the request is being detached */
+ break;
+
+ default:
+ break;
+ }
}
/** Return the depth of the request's stack
return is_yielded(frame);
}
-/** Indicate to the caller of the interpreter that this request is complete
- *
- */
-void unlang_interpret_request_done(request_t *request)
-{
- unlang_stack_t *stack = request->stack;
- unlang_interpret_t *intp;
-
- if (!fr_cond_assert(stack != NULL)) return;
-
- intp = stack->intp;
-
- if (request_is_internal(request)) {
- intp->funcs.done_internal(request, stack->result, intp->uctx);
- } else {
- intp->funcs.done_external(request, stack->result, intp->uctx);
- }
-}
-
/** Mark a request as resumable.
*
* It's not called "unlang_interpret", because it doesn't actually
{
unlang_interpret_t *intp;
+ fr_assert(funcs->init_internal);
+
+ fr_assert(funcs->done_internal);
+ fr_assert(funcs->done_detached);
+ fr_assert(funcs->done_external);
+
+ fr_assert(funcs->detach);
+ fr_assert(funcs->stop);
+ fr_assert(funcs->yield);
+ fr_assert(funcs->resume);
+ fr_assert(funcs->mark_runnable);
+ fr_assert(funcs->scheduled);
+
MEM(intp = talloc(ctx, unlang_interpret_t));
*intp = (unlang_interpret_t){
.el = el,
*/
typedef void (*unlang_request_done_t)(request_t *request, rlm_rcode_t rcode, void *uctx);
+/** Stop a request from running
+ *
+ * This is called whenever a request has been signalled to stop
+ */
+typedef void (*unlang_request_stop_t)(request_t *request, void *uctx);
+
/** Signal the owner of the interpreter that a request has yielded
*
* This is called whenever a request has given control back to the interpeter.
* request management than FeeRADIUS worker threads.
*/
typedef struct {
- unlang_request_init_t init_internal; //!< Function called to initialise a request.
+ /*
+ * There's no init_external as this is done
+ * before the external request is handed off
+ * to the interpreter.
+ */
+ unlang_request_init_t init_internal; //!< Function called to initialise an internal request.
+
+ unlang_request_done_t done_external; //!< Function called when a external request completes.
unlang_request_done_t done_internal; //!< Function called when an internal request completes.
- unlang_request_done_t done_external; //!< Function called when an internal request completes.
+ unlang_request_done_t done_detached; //!< Function called when a detached request completes.
+
+ unlang_request_init_t detach; //!< Function called when a request is detached.
+ unlang_request_stop_t stop; //!< function called when a request is signalled to stop.
unlang_request_yield_t yield; //!< Function called when a request yields.
unlang_request_resume_t resume; //!< Function called when a request is resumed.
unlang_request_runnable_t mark_runnable; //!< Function called when a request needs to be
#include "interpret_priv.h"
#include <freeradius-devel/server/module.h>
+#include <freeradius-devel/server/request.h>
typedef struct {
fr_heap_t *runnable;
unlang_interpret_t *intp;
} unlang_interpret_synchronous_t;
-
/** Internal request (i.e. one generated by the interpreter) is now complete
*
*/
{
unlang_interpret_synchronous_t *intps = uctx;
- RDEBUG3("Initialising synchronous request");
+ RDEBUG3("Initialising internal synchronous request");
unlang_interpret_set(request, intps->intp);
fr_heap_insert(intps->runnable, request);
}
-/** Internal request (i.e. one generated by the interpreter) is now complete
- *
- */
-static void _request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
-{
- RDEBUG3("Done synchronous request");
-}
-
/** External request is now complete
*
*/
RDEBUG3("Synchronous done external request");
}
+/** Internal request (i.e. one generated by the interpreter) is now complete
+ *
+ */
+static void _request_done_internal(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
+{
+ RDEBUG3("Done synchronous internal request");
+
+ /* Request will be cleaned up by whatever created it */
+}
+
+static void _request_done_detached(request_t *request, UNUSED rlm_rcode_t rcode, UNUSED void *uctx)
+{
+ RDEBUG3("Done synchronous detached request");
+
+ /*
+ * If we're the top level interpreter
+ * then free the detached request.
+ */
+ if (unlang_interpret_stack_depth(request) == 0) talloc_free(request);
+}
+
+/** We don't need to do anything for internal -> detached
+ *
+ */
+static void _request_detach(request_t *request, UNUSED void *uctx)
+{
+ RDEBUG3("Synchronous request detached");
+}
+
+/** Request has been stopped
+ *
+ * Clean up execution state
+ */
+static void _request_stop(request_t *request, void *uctx)
+{
+ unlang_interpret_synchronous_t *intps = uctx;
+
+ RDEBUG3("Stopped detached request");
+
+ fr_heap_extract(intps->runnable, request);
+}
+
/** Request is now runnable
*
*/
MEM(intps->intp = unlang_interpret_init(intps, intps->el,
&(unlang_request_func_t){
.init_internal = _request_init_internal,
- .done_internal = _request_done_internal,
+
.done_external = _request_done_external,
- .mark_runnable = _request_runnable,
+ .done_internal = _request_done_internal,
+ .done_detached = _request_done_detached,
+
+ .detach = _request_detach,
+ .stop = _request_stop,
.yield = _request_yield,
.resume = _request_resume,
+ .mark_runnable = _request_runnable,
.scheduled = _request_scheduled
},
intps));
{
request_t *child;
- child = request_alloc(detachable ? NULL : parent,
- (&(request_init_args_t){
- .parent = parent,
- .namespace = namespace,
- .detachable = detachable
- }));
+ child = request_alloc_internal(detachable ? NULL : parent,
+ (&(request_init_args_t){
+ .parent = parent,
+ .namespace = namespace,
+ .detachable = detachable
+ }));
if (!child) return NULL;
/*
state = talloc_get_type_abort(frame_current(request->parent), unlang_frame_state_subrequest_t);
- /*
- * Ignore signals if the parent didn't want the child
- * to be detached.
- */
- if (!state->detachable) return;
-
/*
* Place child's state back inside the parent
*/
static void bfd_trigger(bfd_state_t *session)
{
fr_radius_packet_t packet;
- request_t *request = request_local_alloc(session, NULL);
+ request_t *request = request_local_alloc_external(session, NULL);
char buffer[256];
snprintf(buffer, sizeof(buffer), "server.bfd.%s",
request_t *request;
fr_radius_packet_t *packet, *reply;
- request = request_alloc(session, NULL);
+ request = request_alloc_external(session, NULL);
packet = fr_radius_packet_alloc(request, 0);
reply = fr_radius_packet_alloc(request, 0);
/*
* Allocate a fake request_t structure.
*/
- fake = request_alloc(request, &(request_init_args_t){ .parent = request });
+ fake = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
fr_assert(fr_pair_list_empty(&fake->request_pairs));
t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);
/*
* FIXME: Actually proxy stuff
*/
- request->proxy = request_alloc(request, &(request_init_args_t){ .parent = request });
+ request->proxy = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
request->proxy->packet = talloc_steal(request->proxy, fake->packet);
memset(&request->proxy->packet->src_ipaddr, 0,
break;
case PEAP_STATUS_WAIT_FOR_SOH_RESPONSE:
- fake = request_alloc(request, &(request_init_args_t){ .parent = request });
+ fake = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
fr_assert(fr_pair_list_empty(&fake->request_pairs));
eap_peap_soh_verify(fake, data, data_len);
setup_fake_request(request, fake, t);
goto finish;
}
- fake = request_alloc(request, &(request_init_args_t){ .parent = request });
+ fake = request_alloc_internal(request, &(request_init_args_t){ .parent = request });
fr_assert(fr_pair_list_empty(&fake->request_pairs));
switch (t->status) {
* head before the module destructor
* runs.
*/
- request = request_local_alloc(u, NULL);
+ request = request_local_alloc_external(u, NULL);
request->async = talloc_zero(request, fr_async_t);
talloc_const_free(request->name);
request->name = talloc_strdup(request, h->module_name);