Files
openwrt-R7800-nss/package/utils/ucode/patches/102-ubus-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

212 lines
5.2 KiB
Diff

From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 11 Jun 2025 18:40:10 +0200
Subject: [PATCH] ubus: 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/ubus.c
+++ b/lib/ubus.c
@@ -575,6 +575,40 @@ uc_ubus_call_cb(struct ubus_request *req
}
static void
+uc_ubus_vm_handle_exception(uc_vm_t *vm)
+{
+ uc_value_t *exh, *val;
+
+ exh = uc_vm_registry_get(vm, "ubus.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;
+
+error:
+ uloop_end();
+}
+
+static bool
+uc_ubus_vm_call(uc_vm_t *vm, bool mcall, size_t nargs)
+{
+ if (uc_vm_call(vm, mcall, nargs) == EXCEPTION_NONE)
+ return true;
+
+ uc_ubus_vm_handle_exception(vm);
+
+ return false;
+}
+
+static void
uc_ubus_call_user_cb(uc_ubus_deferred_t *defer, int ret, uc_value_t *reply)
{
uc_value_t *this = ucv_get(defer->res);
@@ -625,10 +659,8 @@ uc_ubus_call_data_user_cb(struct ubus_re
uc_vm_stack_push(vm, ucv_get(func));
uc_vm_stack_push(vm, ucv_get(reply));
- if (uc_vm_call(vm, true, 1) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 1))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
}
@@ -647,10 +679,8 @@ uc_ubus_call_fd_cb(struct ubus_request *
uc_vm_stack_push(vm, ucv_get(func));
uc_vm_stack_push(vm, ucv_int64_new(fd));
- if (uc_vm_call(vm, true, 1) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 1))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
}
@@ -929,10 +959,8 @@ uc_ubus_defer_common(uc_vm_t *vm, uc_ubu
uc_vm_stack_push(vm, ucv_get(replycb));
uc_vm_stack_push(vm, ucv_int64_new(rv));
- if (uc_vm_call(vm, false, 1) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, false, 1))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
ucv_put(res->res);
}
@@ -1201,10 +1229,8 @@ uc_ubus_object_notify_data_cb(struct ubu
uc_vm_stack_push(vm, ucv_int64_new(type));
uc_vm_stack_push(vm, blob_array_to_ucv(vm, blob_data(msg), blob_len(msg), true));
- if (uc_vm_call(vm, true, 2) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 2))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
}
@@ -1224,10 +1250,8 @@ uc_ubus_object_notify_status_cb(struct u
uc_vm_stack_push(vm, ucv_int64_new(idx));
uc_vm_stack_push(vm, ucv_int64_new(ret));
- if (uc_vm_call(vm, true, 2) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 2))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
}
@@ -1247,10 +1271,8 @@ uc_ubus_object_notify_complete_cb(struct
uc_vm_stack_push(vm, ucv_int64_new(idx));
uc_vm_stack_push(vm, ucv_int64_new(ret));
- if (uc_vm_call(vm, true, 2) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 2))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
notifyctx->complete = true;
@@ -1581,7 +1603,7 @@ uc_ubus_handle_reply_common(struct ubus_
/* treat other exceptions as fatal and halt uloop */
default:
uc_ubus_request_finish_common(callctx, UBUS_STATUS_UNKNOWN_ERROR);
- uloop_end();
+ uc_ubus_vm_handle_exception(vm);
break;
}
@@ -1640,10 +1662,8 @@ uc_ubus_object_subscribe_cb(struct ubus_
uc_vm_stack_push(uuobj->vm, ucv_get(uuobj->res));
uc_vm_stack_push(uuobj->vm, ucv_get(func));
- if (uc_vm_call(uuobj->vm, true, 0) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(uuobj->vm, true, 0))
ucv_put(uc_vm_stack_pop(uuobj->vm));
- else
- uloop_end();
}
static bool
@@ -1919,10 +1939,8 @@ uc_ubus_listener_cb(struct ubus_context
uc_vm_stack_push(vm, ucv_string_new(type));
uc_vm_stack_push(vm, blob_array_to_ucv(vm, blob_data(msg), blob_len(msg), true));
- if (uc_vm_call(vm, true, 2) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 2))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
static uc_value_t *
@@ -2042,10 +2060,8 @@ uc_ubus_subscriber_remove_cb(struct ubus
uc_vm_stack_push(vm, ucv_get(func));
uc_vm_stack_push(vm, ucv_uint64_new(id));
- if (uc_vm_call(vm, true, 1) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(vm, true, 1))
ucv_put(uc_vm_stack_pop(vm));
- else
- uloop_end();
}
static uc_value_t *
@@ -2370,10 +2386,8 @@ uc_ubus_channel_disconnect_cb(struct ubu
uc_vm_stack_push(c->vm, ucv_get(c->res));
uc_vm_stack_push(c->vm, ucv_get(func));
- if (uc_vm_call(c->vm, true, 0) == EXCEPTION_NONE)
+ if (uc_ubus_vm_call(c->vm, true, 0))
ucv_put(uc_vm_stack_pop(c->vm));
- else
- uloop_end();
}
blob_buf_free(&c->buf);
@@ -2474,10 +2488,28 @@ uc_ubus_channel_connect(uc_vm_t *vm, siz
}
+static uc_value_t *
+uc_ubus_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, "ubus.ex_handler"));
+
+ if (arg && !ucv_is_callable(arg))
+ return NULL;
+
+ uc_vm_registry_set(vm, "ubus.ex_handler", ucv_get(arg));
+
+ return ucv_boolean_new(true);
+}
+
+
static const uc_function_list_t global_fns[] = {
{ "error", uc_ubus_error },
{ "connect", uc_ubus_connect },
{ "open_channel", uc_ubus_channel_connect },
+ { "guard", uc_ubus_guard },
};
static const uc_function_list_t conn_fns[] = {