]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Dynamically allocate modcall stack state
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 May 2017 03:13:20 +0000 (23:13 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 26 May 2017 01:06:45 +0000 (21:06 -0400)
src/include/interpreter.h
src/main/request.c
src/main/unlang_interpret.c

index fbc25e65eace2a10f9359316af9a98bd0c330599..b6c8aa35eca96f14efe30f2122766fc671957af2 100644 (file)
@@ -195,7 +195,7 @@ typedef struct {
  */
 typedef struct {
        module_thread_instance_t *thread;       //!< thread-local data for this module
-} unlang_stack_entry_modcall_t;
+} unlang_stack_state_modcall_t;
 
 /** State of a foreach loop
  *
@@ -208,7 +208,7 @@ typedef struct {
 #ifndef NDEBUG
        int                     indent;         //!< for catching indentation issues
 #endif
-} unlang_stack_entry_foreach_t;
+} unlang_stack_state_foreach_t;
 
 /** State of a redundant operation
  *
@@ -216,13 +216,13 @@ typedef struct {
 typedef struct {
        unlang_t                *child;
        unlang_t                *found;
-} unlang_stack_entry_redundant_t;
+} unlang_stack_state_redundant_t;
 
 typedef union {
-       unlang_stack_entry_modcall_t    modcall;        //!< State for a modcall.
-       unlang_stack_entry_foreach_t    foreach;        //!< Foreach iterator state.
-       unlang_stack_entry_redundant_t  redundant;      //!< Redundant section state.
-} unlang_stack_entry_t;
+       unlang_stack_state_modcall_t    modcall;        //!< State for a modcall.
+       unlang_stack_state_foreach_t    foreach;        //!< Foreach iterator state.
+       unlang_stack_state_redundant_t  redundant;      //!< Redundant section state.
+} unlang_stack_state_t;
 
 /** Our interpreter stack, as distinct from the C stack
  *
@@ -238,14 +238,6 @@ typedef union {
  */
 typedef struct {
        unlang_t                *instruction;                   //!< The unlang node we're evaluating.
-       rlm_rcode_t             result;
-       int                     priority;
-       unlang_type_t           unwind;                         //!< Unwind to this one if it exists.
-       bool                    do_next_sibling : 1;
-       bool                    was_if : 1;
-       bool                    if_taken : 1;
-       bool                    resume : 1;
-       bool                    top_frame : 1;
 
        /** Stack frame specialisations
         *
@@ -256,10 +248,22 @@ typedef struct {
         * Which stack_entry specialisation to use is determined by the
         * instruction->type.
         */
+       void                    *state;
+
+       rlm_rcode_t             result;
+       int                     priority;
+       unlang_type_t           unwind;                         //!< Unwind to this one if it exists.
+                                                               //!< This is used for break and return.
+
+       bool                    do_next_sibling : 1;
+       bool                    was_if : 1;
+       bool                    if_taken : 1;
+       bool                    resume : 1;
+       bool                    top_frame : 1;
+
        union {
-               unlang_stack_entry_modcall_t    modcall;        //!< State for a modcall.
-               unlang_stack_entry_foreach_t    foreach;        //!< Foreach iterator state.
-               unlang_stack_entry_redundant_t  redundant;      //!< Redundant section state.
+               unlang_stack_state_foreach_t    foreach;        //!< Foreach iterator state.
+               unlang_stack_state_redundant_t  redundant;      //!< Redundant section state.
        };
 } unlang_stack_frame_t;
 
index d593e3fd4987a093373142f1bd02afa0f45d4364..3b4cc9fb6ae2b180056d4310499231b355da87e9 100644 (file)
@@ -126,7 +126,7 @@ REQUEST *request_alloc(TALLOC_CTX *ctx)
         *      like too low level to make into a tuneable.
         */
        request->stack = talloc_pooled_object(request, unlang_stack_t, UNLANG_STACK_MAX / 4,
-                                             sizeof(unlang_stack_entry_t));
+                                             sizeof(unlang_stack_state_t));
 #else
        request->stack = talloc_zero(request, unlang_stack_t);
 #endif
index a8c71f1a69244d3e77e2845cf6d23a2d669aa132..9a67011e2622c7fe44a0ea3896c5b5c9d1fd00af 100644 (file)
@@ -79,6 +79,7 @@ static inline void unlang_push(unlang_stack_t *stack, unlang_t *program, rlm_rco
        next->was_if = false;
        next->if_taken = false;
        next->resume = false;
+       next->state = NULL;
 }
 
 static inline void unlang_pop(unlang_stack_t *stack)
@@ -798,6 +799,7 @@ static unlang_action_t unlang_module_call(REQUEST *request, unlang_stack_t *stac
        unlang_module_call_t            *sp;
        unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_t                        *instruction = frame->instruction;
+       unlang_stack_state_modcall_t    *modcall_state;
 
        /*
         *      Process a stand-alone child, and fall through
@@ -811,30 +813,36 @@ static unlang_action_t unlang_module_call(REQUEST *request, unlang_stack_t *stac
         */
        if (request->master_state == REQUEST_STOP_PROCESSING) return UNLANG_ACTION_STOP_PROCESSING;
 
-       RDEBUG4("[%i] %s - %s (%s)", stack->depth, __FUNCTION__, sp->module_instance->name, sp->module_instance->module->name);
+       RDEBUG4("[%i] %s - %s (%s)", stack->depth, __FUNCTION__,
+               sp->module_instance->name, sp->module_instance->module->name);
 
+       /*
+        *      Return administratively configured return code
+        */
        if (sp->module_instance->force) {
                request->rcode = sp->module_instance->code;
                goto done;
        }
 
+       frame->state = modcall_state = talloc_zero(stack, unlang_stack_state_modcall_t);
+
        /*
         *      Grab the thread/module specific data if any exists.
         */
-       frame->modcall.thread = module_thread_instance_find(sp->module_instance);
-       rad_assert(frame->modcall.thread != NULL);
+       modcall_state->thread = module_thread_instance_find(sp->module_instance);
+       rad_assert(modcall_state->thread != NULL);
 
        /*
         *      For logging unresponsive children.
         */
        request->module = sp->module_instance->name;
-       frame->modcall.thread->total_calls++;
+       modcall_state->thread->total_calls++;
 
        /*
         *      Lock is noop unless instance->mutex is set.
         */
        safe_lock(sp->module_instance);
-       request->rcode = sp->method(sp->module_instance->data, frame->modcall.thread->data, request);
+       request->rcode = sp->method(sp->module_instance->data, modcall_state->thread->data, request);
        safe_unlock(sp->module_instance);
 
        request->module = NULL;
@@ -849,7 +857,7 @@ static unlang_action_t unlang_module_call(REQUEST *request, unlang_stack_t *stac
        }
 
        if (*presult == RLM_MODULE_YIELD) {
-               frame->modcall.thread->active_callers++;
+               modcall_state->thread->active_callers++;
        } else {
                *priority = instruction->actions[*presult];
        }
@@ -969,6 +977,8 @@ static unlang_action_t unlang_module_resumption(REQUEST *request, unlang_stack_t
        unlang_t                        *instruction = frame->instruction;
        unlang_module_resumption_t      *mr = unlang_generic_to_module_resumption(instruction);
        unlang_module_call_t            *sp;
+       unlang_stack_state_modcall_t    *modcall_state = talloc_get_type_abort(frame->state,
+                                                                              unlang_stack_state_modcall_t);
        void                            *mutable;
 
        sp = &mr->module;
@@ -1003,7 +1013,7 @@ static unlang_action_t unlang_module_resumption(REQUEST *request, unlang_stack_t
        }
 
        if (*presult != RLM_MODULE_YIELD) {
-               frame->modcall.thread->active_callers--;
+               modcall_state->thread->active_callers--;
                *priority = instruction->actions[*presult];
        }
 
@@ -1600,6 +1610,8 @@ int unlang_event_timeout_add(REQUEST *request, fr_unlang_timeout_callback_t call
        unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_event_t                  *ev;
        unlang_module_call_t            *sp;
+       unlang_stack_state_modcall_t    *modcall_state = talloc_get_type_abort(frame->state,
+                                                                              unlang_stack_state_modcall_t);
 
        rad_assert(stack->depth > 0);
        rad_assert((frame->instruction->type == UNLANG_TYPE_MODULE_CALL) ||
@@ -1613,7 +1625,7 @@ int unlang_event_timeout_add(REQUEST *request, fr_unlang_timeout_callback_t call
        ev->fd = -1;
        ev->timeout = callback;
        ev->inst = sp->module_instance->data;
-       ev->thread = frame->modcall.thread;
+       ev->thread = modcall_state->thread;
        ev->ctx = ctx;
 
        if (fr_event_timer_insert(request->el, unlang_event_timeout_handler, ev, when, &(ev->ev)) < 0) {
@@ -1679,6 +1691,8 @@ int unlang_event_fd_add(REQUEST *request,
        unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_event_t                  *ev;
        unlang_module_call_t            *sp;
+       unlang_stack_state_modcall_t    *modcall_state = talloc_get_type_abort(frame->state,
+                                                                              unlang_stack_state_modcall_t);
 
        rad_assert(stack->depth > 0);
 
@@ -1695,7 +1709,7 @@ int unlang_event_fd_add(REQUEST *request,
        ev->fd_write = write;
        ev->fd_error = error;
        ev->inst = sp->module_instance->data;
-       ev->thread = frame->modcall.thread;
+       ev->thread = modcall_state->thread;
        ev->ctx = ctx;
 
        /*
@@ -1845,6 +1859,8 @@ rlm_rcode_t unlang_module_yield(REQUEST *request, fr_unlang_module_resume_t call
        unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
        unlang_module_resumption_t      *mr;
        unlang_module_call_t            *sp;
+       unlang_stack_state_modcall_t    *modcall_state = talloc_get_type_abort(frame->state,
+                                                                              unlang_stack_state_modcall_t);
 
        rad_assert(stack->depth > 0);
 
@@ -1856,7 +1872,7 @@ rlm_rcode_t unlang_module_yield(REQUEST *request, fr_unlang_module_resume_t call
        rad_assert(mr != NULL);
 
        memcpy(&mr->module, frame->instruction, sizeof(mr->module));
-       mr->thread = frame->modcall.thread;
+       mr->thread = modcall_state->thread;
        mr->module.self.type = UNLANG_TYPE_MODULE_RESUME;
        mr->callback = callback;
        mr->signal_callback = signal_callback;