Files
openwrt-R7800-nss/package/utils/ucode/patches/101-uloop-add-guard-function.patch
Felix Fietkau b626262226 ucode: update ubus/uloop exception handling patches
Function renames and a leak fix

Signed-off-by: Felix Fietkau <nbd@nbd.name>
2025-07-14 12:16:50 +02:00

143 lines
3.2 KiB
Diff

From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 11 Jun 2025 18:31:39 +0200
Subject: [PATCH] uloop: add guard() function
This allows calling the provided handler on exceptions, avoiding the
existing behavior of calling uloop_end().
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/lib/uloop.c
+++ b/lib/uloop.c
@@ -114,27 +114,48 @@ uc_uloop_cb_free(uc_uloop_cb_t *cb)
}
static bool
+uc_uloop_vm_call(uc_vm_t *vm, bool mcall, size_t nargs)
+{
+ uc_value_t *exh, *val;
+
+ if (uc_vm_call(vm, mcall, nargs) == EXCEPTION_NONE)
+ return true;
+
+ exh = uc_vm_registry_get(vm, "uloop.ex_handler");
+ if (!ucv_is_callable(exh))
+ goto error;
+
+ val = uc_vm_exception_object(vm);
+ uc_vm_stack_push(vm, ucv_get(exh));
+ uc_vm_stack_push(vm, val);
+
+ if (uc_vm_call(vm, false, 1) != EXCEPTION_NONE)
+ goto error;
+
+ ucv_put(uc_vm_stack_pop(vm));
+
+ return false;
+
+error:
+ uloop_end();
+ return false;
+}
+
+static void
uc_uloop_cb_invoke(uc_uloop_cb_t *cb, uc_value_t *arg)
{
uc_vm_t *vm = cb->vm;
uc_value_t *func = ucv_resource_value_get(cb->obj, 0);
if (!ucv_is_callable(func))
- return false;
+ return;
uc_vm_stack_push(vm, ucv_get(cb->obj));
uc_vm_stack_push(vm, ucv_get(func));
uc_vm_stack_push(vm, ucv_get(arg));
- if (uc_vm_call(vm, true, 1) != EXCEPTION_NONE) {
- uloop_end();
-
- return false;
- }
-
- ucv_put(uc_vm_stack_pop(vm));
-
- return true;
+ if (uc_uloop_vm_call(vm, true, 1))
+ ucv_put(uc_vm_stack_pop(vm));
}
/**
@@ -1550,11 +1571,8 @@ uc_uloop_task_output_cb(struct uloop_fd
uc_vm_stack_push(vm, ucv_get(obj));
uc_vm_stack_push(vm, ucv_get(task->input_cb));
- if (uc_vm_call(vm, true, 0) != EXCEPTION_NONE) {
- uloop_end();
-
+ if (!uc_uloop_vm_call(vm, true, 0))
return;
- }
msg = uc_vm_stack_pop(vm);
uc_uloop_pipe_send_common(vm, msg, task->input_fd);
@@ -1572,14 +1590,10 @@ uc_uloop_task_output_cb(struct uloop_fd
uc_vm_stack_push(vm, ucv_get(task->output_cb));
uc_vm_stack_push(vm, msg);
- if (uc_vm_call(vm, true, 1) == EXCEPTION_NONE) {
- ucv_put(uc_vm_stack_pop(vm));
- }
- else {
- uloop_end();
-
+ if (!uc_uloop_vm_call(vm, true, 1))
return;
- }
+
+ ucv_put(uc_vm_stack_pop(vm));
}
else {
ucv_put(msg);
@@ -1703,7 +1717,7 @@ uc_uloop_task(uc_vm_t *vm, size_t nargs)
uc_vm_stack_push(vm, func);
uc_vm_stack_push(vm, ucv_get(p));
- if (uc_vm_call(vm, false, 1) == EXCEPTION_NONE) {
+ if (uc_uloop_vm_call(vm, false, 1)) {
res = uc_vm_stack_pop(vm);
uc_uloop_pipe_send_common(vm, res, tpipe->output);
ucv_put(res);
@@ -2167,6 +2181,22 @@ uc_uloop_signal(uc_vm_t *vm, size_t narg
}
#endif
+static uc_value_t *
+uc_uloop_guard(uc_vm_t *vm, size_t nargs)
+{
+ uc_value_t *arg = uc_fn_arg(0);
+
+ if (!nargs)
+ return ucv_get(uc_vm_registry_get(vm, "uloop.ex_handler"));
+
+ if (arg && !ucv_is_callable(arg))
+ return NULL;
+
+ uc_vm_registry_set(vm, "uloop.ex_handler", ucv_get(arg));
+
+ return ucv_boolean_new(true);
+}
+
static const uc_function_list_t timer_fns[] = {
{ "set", uc_uloop_timer_set },
@@ -2233,6 +2263,7 @@ static const uc_function_list_t global_f
#ifdef HAVE_ULOOP_SIGNAL
{ "signal", uc_uloop_signal },
#endif
+ { "guard", uc_uloop_guard },
};