return compile_empty(parent, unlang_ctx, NULL, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_GROUP_TYPE_SIMPLE,
UNLANG_TYPE_BREAK, COND_TYPE_INVALID);
}
+
+static unlang_t *compile_detach(unlang_t *parent, unlang_compile_t *unlang_ctx, CONF_ITEM const *ci)
+{
+ if (parent->type != UNLANG_TYPE_CREATE) {
+ cf_log_err(ci, "'detach' can only be used in a 'create' section");
+ return NULL;
+ }
+
+ /*
+ * This really overloads the functionality of
+ * cf_item_next().
+ */
+ if (!cf_item_next(ci, ci)) {
+ cf_log_err(ci, "'detach' cannot be used as the last entry in a section");
+ return NULL;
+ }
+
+ return compile_empty(parent, unlang_ctx, NULL, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_GROUP_TYPE_SIMPLE,
+ UNLANG_TYPE_DETACH, COND_TYPE_INVALID);
+}
#endif
static unlang_t *compile_xlat_inline(unlang_t *parent,
cf_log_err(ci, "Invalid use of 'break'");
return NULL;
+ } else if (strcmp(modrefname, "detach") == 0) {
+ cf_log_err(ci, "Invalid use of 'detach'");
+ return NULL;
+
} else if (strcmp(modrefname, "return") == 0) {
cf_log_err(ci, "Invalid use of 'return'");
return NULL;
return compile_break(parent, unlang_ctx, ci);
}
+ if (strcmp(modrefname, "detach") == 0) {
+ return compile_detach(parent, unlang_ctx, ci);
+ }
+
if (strcmp(modrefname, "return") == 0) {
return compile_empty(parent, unlang_ctx, NULL, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_GROUP_TYPE_SIMPLE, UNLANG_TYPE_RETURN, COND_TYPE_INVALID);
}
return RLM_MODULE_YIELD;
}
+static unlang_action_t unlang_detach(REQUEST *request, unlang_stack_t *stack,
+ rlm_rcode_t *presult, int *priority)
+{
+ unlang_stack_frame_t *frame = &stack->frame[stack->depth];
+ unlang_t *instruction = frame->instruction;
+
+ rad_assert(instruction->parent->type == UNLANG_TYPE_CREATE);
+ RDEBUG2("%s", unlang_ops[instruction->type].name);
+
+ if (request_detach(request) < 0) {
+ ERROR("Failed detaching child");
+ *presult = RLM_MODULE_FAIL;
+ *priority = 0;
+ return UNLANG_ACTION_CALCULATE_RESULT;
+ }
+
+ /*
+ * request_detach() doesn't set the "detached" flag, but
+ * it does set the backlog...
+ */
+ request->async->detached = true;
+ rad_assert(request->backlog != NULL);
+
+ *presult = RLM_MODULE_YIELD;
+ return UNLANG_ACTION_CALCULATE_RESULT;
+}
+
static unlang_action_t unlang_create(REQUEST *request, unlang_stack_t *stack,
rlm_rcode_t *presult, int *priority)
{
return UNLANG_ACTION_CALCULATE_RESULT;
}
+ /*
+ * As a special case, if the child is "detach", detach
+ * the child, insert the child into the runnable queue,
+ * and keep going with the parent.
+ */
+ {
+ unlang_stack_t *child_stack = child->stack;
+ unlang_stack_frame_t *child_frame = &child_stack->frame[child_stack->depth];
+ unlang_t *child_instruction = child_frame->instruction;
+
+ if (child_instruction->type == UNLANG_TYPE_DETACH) {
+ rad_assert(child->backlog != NULL);
+ fr_heap_insert(child->backlog, child);
+
+ /*
+ * Tell the interpreter to skip the "detach"
+ * stack frame when it continues.
+ */
+ child_frame->instruction = child_frame->next;
+ if (child_frame->instruction) child_frame->next = child_frame->instruction->next;
+
+ *presult = RLM_MODULE_NOOP;
+ *priority = 0;
+ return UNLANG_ACTION_CALCULATE_RESULT;
+ } /* else the child yielded, so we have to yield */
+ }
+
/*
* Create the "resume" stack frame, and have it replace our stack frame.
*/
.func = unlang_create,
.debug_braces = true
},
+ [UNLANG_TYPE_DETACH] = {
+ .name = "detach",
+ .func = unlang_detach,
+ .debug_braces = false
+ },
#endif
[UNLANG_TYPE_XLAT_INLINE] = {
.name = "xlat_inline",
case UNLANG_ACTION_CALCULATE_RESULT:
if (result == RLM_MODULE_YIELD) {
+ /*
+ * Detach is magic. The parent
+ * "create" function takes care
+ * of bumping the instruction
+ * pointer...
+ */
+ if (frame->instruction->type == UNLANG_TYPE_DETACH) {
+ RDEBUG4("** [%i] %s - detaching child with current (%s %d)", stack->depth, __FUNCTION__,
+ fr_int2str(mod_rcode_table, frame->result, "<invalid>"),
+ frame->priority);
+ DUMP_STACK;
+ return RLM_MODULE_YIELD;
+ }
+
rad_assert(frame->instruction->type == UNLANG_TYPE_RESUME);
frame->resume = true;
RDEBUG4("** [%i] %s - yielding with current (%s %d)", stack->depth, __FUNCTION__,