[Tarantool-patches] [PATCH v4 2/6] box/func: provide module_sym_call
Cyrill Gorcunov
gorcunov at gmail.com
Thu Oct 1 16:51:09 MSK 2020
This helpers allow to execute a function bound to
module symbol without claiming to provide credentials
and being registered in "_func" space.
This will be needed to execute unregistered C functions.
Part-of #4642
Signed-off-by: Cyrill Gorcunov <gorcunov at gmail.com>
---
src/box/func.c | 78 +++++++++++++++++++++++++++++---------------------
src/box/func.h | 14 +++++++++
2 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/src/box/func.c b/src/box/func.c
index 75d2abb5f..452866a5d 100644
--- a/src/box/func.c
+++ b/src/box/func.c
@@ -408,6 +408,50 @@ module_sym_unload(struct module_sym *mod_sym)
mod_sym->addr = NULL;
}
+int
+module_sym_call(struct module_sym *mod_sym, struct port *args, struct port *ret)
+{
+ if (mod_sym->addr == NULL) {
+ if (module_sym_load(mod_sym) != 0)
+ return -1;
+ }
+
+ struct region *region = &fiber()->gc;
+ size_t region_svp = region_used(region);
+ uint32_t data_sz;
+ const char *data = port_get_msgpack(args, &data_sz);
+ if (data == NULL)
+ return -1;
+
+ port_c_create(ret);
+ box_function_ctx_t ctx = {
+ .port = ret,
+ };
+
+ /*
+ * Module can be changed after function reload. Also
+ * keep in mind that stored C procedure may yield inside.
+ */
+ struct module *module = mod_sym->module;
+ assert(module != NULL);
+ ++module->calls;
+ int rc = mod_sym->addr(&ctx, data, data + data_sz);
+ --module->calls;
+ module_gc(module);
+ region_truncate(region, region_svp);
+
+ if (rc != 0) {
+ if (diag_last_error(&fiber()->diag) == NULL) {
+ /* Stored procedure forget to set diag */
+ diag_set(ClientError, ER_PROC_C, "unknown error");
+ }
+ port_destroy(ret);
+ return -1;
+ }
+
+ return rc;
+}
+
int
module_reload(const char *package, const char *package_end, struct module **module)
{
@@ -544,39 +588,9 @@ func_c_call(struct func *base, struct port *args, struct port *ret)
{
assert(base->vtab == &func_c_vtab);
assert(base != NULL && base->def->language == FUNC_LANGUAGE_C);
- struct func_c *func = (struct func_c *) base;
- if (func->mod_sym.addr == NULL) {
- if (module_sym_load(&func->mod_sym) != 0)
- return -1;
- }
-
- struct region *region = &fiber()->gc;
- size_t region_svp = region_used(region);
- uint32_t data_sz;
- const char *data = port_get_msgpack(args, &data_sz);
- if (data == NULL)
- return -1;
-
- port_c_create(ret);
- box_function_ctx_t ctx = { ret };
- /* Module can be changed after function reload. */
- struct module *module = func->mod_sym.module;
- assert(module != NULL);
- ++module->calls;
- int rc = func->mod_sym.addr(&ctx, data, data + data_sz);
- --module->calls;
- module_gc(module);
- region_truncate(region, region_svp);
- if (rc != 0) {
- if (diag_last_error(&fiber()->diag) == NULL) {
- /* Stored procedure forget to set diag */
- diag_set(ClientError, ER_PROC_C, "unknown error");
- }
- port_destroy(ret);
- return -1;
- }
- return rc;
+ struct func_c *func = (struct func_c *) base;
+ return module_sym_call(&func->mod_sym, args, ret);
}
static struct func_vtab func_c_vtab = {
diff --git a/src/box/func.h b/src/box/func.h
index acf2df9a9..35f4e320c 100644
--- a/src/box/func.h
+++ b/src/box/func.h
@@ -151,6 +151,20 @@ module_sym_load(struct module_sym *mod_sym);
void
module_sym_unload(struct module_sym *mod_sym);
+/**
+ * Execute a module symbol call.
+ *
+ * @param mod_sym module symbol pointer.
+ * @param args arguments to pass to the callee.
+ * @param ret execution results passed to the caller.
+ *
+ * @retval -1 on error.
+ * @retval 0 on success.
+ */
+int
+module_sym_call(struct module_sym *mod_sym, struct port *args,
+ struct port *ret);
+
/**
* Reload dynamically loadable module.
*
--
2.26.2
More information about the Tarantool-patches
mailing list