From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-f68.google.com (mail-lf1-f68.google.com [209.85.167.68]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id B18D544643A for ; Thu, 1 Oct 2020 16:51:41 +0300 (MSK) Received: by mail-lf1-f68.google.com with SMTP id u8so6687147lff.1 for ; Thu, 01 Oct 2020 06:51:41 -0700 (PDT) From: Cyrill Gorcunov Date: Thu, 1 Oct 2020 16:51:09 +0300 Message-Id: <20201001135113.329664-3-gorcunov@gmail.com> In-Reply-To: <20201001135113.329664-1-gorcunov@gmail.com> References: <20201001135113.329664-1-gorcunov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v4 2/6] box/func: provide module_sym_call List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tml Cc: Vladislav Shpilevoy , Alexander Turenko 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 --- 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