]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add custom stack dump functions
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 23 Jun 2021 19:41:22 +0000 (14:41 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 24 Jun 2021 00:08:59 +0000 (19:08 -0500)
These can print out more information about the frame state

src/lib/unlang/function.c
src/lib/unlang/function.h
src/lib/unlang/interpret.c
src/lib/unlang/unlang_priv.h

index d4558c3c6d5a477d99644beedd1a4918536dfc9e..b7527f4d871151ff91f3f5e1bc64c9dd1972de63 100644 (file)
@@ -33,8 +33,11 @@ RCSID("$Id$")
  */
 typedef struct {
        unlang_function_t               func;                   //!< To call when going down the stack.
+       char const                      *func_name;             //!< Debug name for the function.
        unlang_function_t               repeat;                 //!< To call when going back up the stack.
+       char const                      *repeat_name;           //!< Debug name for the repeat function.
        unlang_function_signal_t        signal;                 //!< Signal function to call.
+       char const                      *signal_name;           //!< Debug name for the signal function.
        void                            *uctx;                  //!< Uctx to pass to function.
 } unlang_frame_state_func_t;
 
@@ -86,7 +89,7 @@ static unlang_action_t unlang_function_call_repeat(rlm_rcode_t *p_result, reques
         */
        caller = request->module;
        request->module = NULL;
-       RDEBUG4("Calling repeat function %p", state->repeat);
+       RDEBUG4("Calling repeat function %p (%s)", state->repeat, state->repeat_name);
        ua = state->repeat(p_result, &frame->priority, request, state->uctx);
        request->module = caller;
 
@@ -112,7 +115,7 @@ static unlang_action_t unlang_function_call(rlm_rcode_t *p_result, request_t *re
        caller = request->module;
        request->module = NULL;
 
-       RDEBUG4("Calling function %p", state->func);
+       RDEBUG4("Calling function %p (%s)", state->func, state->func_name);
        ua = state->func(p_result, &frame->priority, request, state->uctx);
        switch (ua) {
        case UNLANG_ACTION_STOP_PROCESSING:
@@ -174,13 +177,14 @@ int unlang_function_clear(request_t *request)
  *
  * The function frame being modified must be at the top of the stack.
  *
- * @param[in] request  The current request.
- * @param[in] repeat   the repeat function to set.
+ * @param[in] request          The current request.
+ * @param[in] repeat           the repeat function to set.
+ * @param[in] repeat_name      Name of the repeat function call (for debugging).
  * @return
  *     - 0 on success.
  *      - -1 on failure.
  */
-int unlang_function_repeat(request_t *request, unlang_function_t repeat)
+int _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *repeat_name)
 {
        unlang_stack_t                  *stack = request->stack;
        unlang_stack_frame_t            *frame = &stack->frame[stack->depth];
@@ -199,6 +203,8 @@ int unlang_function_repeat(request_t *request, unlang_function_t repeat)
         *      once the current function returns.
         */
        state->repeat = repeat;
+       state->repeat_name = repeat_name;
+       repeatable_set(frame);
 
        return 0;
 }
@@ -208,18 +214,24 @@ int unlang_function_repeat(request_t *request, unlang_function_t repeat)
  * These can be pushed by any other type of unlang op to allow a submodule or function
  * deeper in the C call stack to establish a new resumption point.
  *
- * @param[in] request  The current request.
- * @param[in] func     to call going up the stack.
- * @param[in] repeat   function to call going back down the stack (may be NULL).
- *                     This may be the same as func.
- * @param[in] signal   function to call if the request is signalled.
- * @param[in] uctx     to pass to func.
+ * @param[in] request          The current request.
+ * @param[in] func             to call going up the stack.
+ * @param[in] func_name                Name of the function call (for debugging).
+ * @param[in] repeat           function to call going back down the stack (may be NULL).
+ *                             This may be the same as func.
+ * @param[in] repeat_name      Name of the repeat function call (for debugging).
+ * @param[in] signal           function to call if the request is signalled.
+ * @param[in] signal_name      Name of the signal function call (for debugging).
+ * @param[in] uctx             to pass to func(s).
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-unlang_action_t unlang_function_push(request_t *request, unlang_function_t func, unlang_function_t repeat,
-                                    unlang_function_signal_t signal, bool top_frame, void *uctx)
+unlang_action_t _unlang_function_push(request_t *request,
+                                     unlang_function_t func, char const *func_name,
+                                     unlang_function_t repeat, char const *repeat_name,
+                                     unlang_function_signal_t signal, char const *signal_name,
+                                     bool top_frame, void *uctx)
 {
        unlang_stack_t                  *stack = request->stack;
        unlang_stack_frame_t            *frame;
@@ -244,8 +256,11 @@ unlang_action_t unlang_function_push(request_t *request, unlang_function_t func,
         */
        state = frame->state;
        state->func = func;
+       state->func_name = func_name;
        state->repeat = repeat;
+       state->repeat_name = repeat_name;
        state->signal = signal;
+       state->signal_name = signal_name;
        state->uctx = uctx;
 
        /*
@@ -256,6 +271,19 @@ unlang_action_t unlang_function_push(request_t *request, unlang_function_t func,
        return UNLANG_ACTION_PUSHED_CHILD;
 }
 
+/** Custom frame state dumper
+ *
+ */
+static void unlang_function_dump(request_t *request, unlang_stack_frame_t *frame)
+{
+       unlang_frame_state_func_t       *state = talloc_get_type_abort(frame->state, unlang_frame_state_func_t);
+
+       RDEBUG2("frame state");
+       if (state->func)   RDEBUG2("function       %p (%s)", state->func, state->func_name);
+       if (state->repeat) RDEBUG2("repeat         %p (%s)", state->repeat, state->repeat_name);
+       if (state->signal) RDEBUG2("signal         %p (%s)", state->signal, state->signal_name);
+}
+
 void unlang_function_init(void)
 {
        unlang_register(UNLANG_TYPE_FUNCTION,
@@ -263,6 +291,7 @@ void unlang_function_init(void)
                                .name = "function",
                                .interpret = unlang_function_call,
                                .signal = unlang_function_signal,
+                               .dump = unlang_function_dump,
                                .debug_braces = false,
                                .frame_state_size = sizeof(unlang_frame_state_func_t),
                                .frame_state_name = "unlang_frame_state_func_t",
index 1bc0b327735fbb7c171aa374c06ea434653fb236..8a9113385fa758e98ece1a25521a032449b35a66 100644 (file)
@@ -58,12 +58,49 @@ typedef void (*unlang_function_signal_t)(request_t *request, fr_state_signal_t a
 
 int            unlang_function_clear(request_t *request) CC_HINT(warn_unused_result);
 
-int            unlang_function_repeat(request_t *request, unlang_function_t repeat) CC_HINT(warn_unused_result);
+int            _unlang_function_repeat(request_t *request, unlang_function_t repeat, char const *name) CC_HINT(warn_unused_result);
 
-unlang_action_t        unlang_function_push(request_t *request,
-                                    unlang_function_t func, unlang_function_t repeat,
-                                    unlang_function_signal_t signal, bool top_frame, void *uctx)
-                                    CC_HINT(warn_unused_result);
+/** Set a new repeat function for an existing function frame
+ *
+ * The function frame being modified must be at the top of the stack.
+ *
+ * @param[in] _request         The current request.
+ * @param[in] _repeat          the repeat function to set.
+ * @return
+ *     - 0 on success.
+ *      - -1 on failure.
+ */
+#define                unlang_function_repeat(_request, _repeat) \
+               _unlang_function_repeat(_request, _repeat, STRINGIFY(_repeat))
+
+unlang_action_t        _unlang_function_push(request_t *request,
+                                     unlang_function_t func, char const *func_name,
+                                     unlang_function_t repeat, char const *repeat_name,
+                                     unlang_function_signal_t signal, char const *signal_name,
+                                     bool top_frame, void *uctx)
+                                     CC_HINT(warn_unused_result);
+
+/** Push a generic function onto the unlang stack
+ *
+ * These can be pushed by any other type of unlang op to allow a submodule or function
+ * deeper in the C call stack to establish a new resumption point.
+ *
+ * @param[in] _request         The current request.
+ * @param[in] _func            to call going up the stack.
+ * @param[in] _repeat          function to call going back down the stack (may be NULL).
+ *                             This may be the same as func.
+ * @param[in] _signal          function to call if the request is signalled.
+ * @param[in] _uctx            to pass to func(s).
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+#define                unlang_function_push(_request, _func, _repeat, _signal, _top_frame, _uctx) \
+               _unlang_function_push(_request, \
+                                     _func, STRINGIFY(_func), \
+                                     _repeat, STRINGIFY(_repeat), \
+                                     _signal, STRINGIFY(_signal), \
+                                     _top_frame, _uctx)
 
 #ifdef __cplusplus
 }
index bccac437296fec78d7e19c4e38b0a29dfff59ee5..e09bdc69aa98b8f75bd2c81865a01af449d5c8cd 100644 (file)
@@ -39,19 +39,19 @@ RCSID("$Id$")
 static _Thread_local unlang_interpret_t *intp_thread_default;
 
 static fr_table_num_ordered_t const unlang_action_table[] = {
-       { L("unwind"),          UNLANG_ACTION_UNWIND },
+       { L("unwind"),                  UNLANG_ACTION_UNWIND },
        { L("calculate-result"),        UNLANG_ACTION_CALCULATE_RESULT },
-       { L("next"),            UNLANG_ACTION_EXECUTE_NEXT },
-       { L("pushed-child"),    UNLANG_ACTION_PUSHED_CHILD },
-       { L("stop"),            UNLANG_ACTION_STOP_PROCESSING },
-       { L("yield"),           UNLANG_ACTION_YIELD }
+       { L("next"),                    UNLANG_ACTION_EXECUTE_NEXT },
+       { L("pushed-child"),            UNLANG_ACTION_PUSHED_CHILD },
+       { L("stop"),                    UNLANG_ACTION_STOP_PROCESSING },
+       { L("yield"),                   UNLANG_ACTION_YIELD }
 };
 static size_t unlang_action_table_len = NUM_ELEMENTS(unlang_action_table);
 
 static fr_table_num_ordered_t const unlang_frame_action_table[] = {
-       { L("pop"),             UNLANG_FRAME_ACTION_POP         },
-       { L("next"),            UNLANG_FRAME_ACTION_NEXT        },
-       { L("yield"),           UNLANG_FRAME_ACTION_YIELD       }
+       { L("pop"),                     UNLANG_FRAME_ACTION_POP         },
+       { L("next"),                    UNLANG_FRAME_ACTION_NEXT        },
+       { L("yield"),                   UNLANG_FRAME_ACTION_YIELD       }
 };
 static size_t unlang_frame_action_table_len = NUM_ELEMENTS(unlang_frame_action_table);
 
@@ -73,6 +73,10 @@ static void instruction_dump(request_t *request, unlang_t const *instruction)
 
 static void frame_dump(request_t *request, unlang_stack_frame_t *frame)
 {
+       unlang_op_t     *op = NULL;
+
+       if (frame->instruction) op = &unlang_ops[frame->instruction->type];
+
        instruction_dump(request, frame->instruction);
 
        RINDENT();
@@ -89,6 +93,12 @@ static void frame_dump(request_t *request, unlang_stack_frame_t *frame)
        RDEBUG2("break_point    %s", is_break_point(frame) ? "yes" : "no");
        RDEBUG2("return_point   %s", is_return_point(frame) ? "yes" : "no");
        RDEBUG2("resumable      %s", is_yielded(frame) ? "yes" : "no");
+
+       /*
+        *      Call the custom frame dump function
+        */
+       if (op && op->dump) op->dump(request, frame);
+
        REXDENT();
 }
 
index 8bd27163d2603990199a425698c129529a956be9..eb447b6bc9a3c8b04f1104291e9b1c41ef423b7e 100644 (file)
@@ -183,6 +183,13 @@ typedef unlang_action_t (*unlang_process_t)(rlm_rcode_t *p_result, request_t *re
 typedef void (*unlang_signal_t)(request_t *request,
                                unlang_stack_frame_t *frame, fr_state_signal_t action);
 
+/** Custom callback for dumping information about frame state
+ *
+ * @param[in] request          The current request.
+ * @param[in] frame            to provide additional information for.
+ */
+typedef void (*unlang_dump_t)(request_t *request, unlang_stack_frame_t *frame);
+
 /** An unlang operation
  *
  * These are like the opcodes in other interpreters.  Each operation, when executed
@@ -195,6 +202,8 @@ typedef struct {
 
        unlang_signal_t         signal;                         //!< Function to signal stop / dup / whatever
 
+       unlang_dump_t           dump;                           //!< Dump additional information about the frame state.
+
        bool                    debug_braces;                   //!< Whether the operation needs to print braces
                                                                ///< in debug mode.