diff mbox series

[01/13] Lua: prepare to extend Lua lifetime

Message ID 20240221082221.11997-2-stefano.babic@swupdate.org
State Accepted
Delegated to: Stefano Babic
Headers show
Series Extend Lua Environemnt and post-failure scripts | expand

Commit Message

Stefano Babic Feb. 21, 2024, 8:22 a.m. UTC
A Lua context is created and destroyed for each Lua scriptthat should
run. This isolates each script, but it does not allow that a later
script can benefit and load a function previously defined.

It was decided that so high isolation is not necessary - instead of
having a context for each script, create a Lua context for each
installation request. The Lua context is then initialized when
sw-description is parsed and removed when the installation has finished,
independently from the state.

Signed-off-by: Stefano Babic <stefano.babic@swupdate.org>
---
 core/installer.c        |  8 ++++++++
 corelib/lua_interface.c | 14 +++++++++-----
 include/lua_util.h      | 12 +++++++-----
 include/swupdate.h      |  1 +
 parser/parser.c         | 16 +++++++++++-----
 5 files changed, 36 insertions(+), 15 deletions(-)

--
2.34.1
diff mbox series

Patch

diff --git a/core/installer.c b/core/installer.c
index 20b5b51e..2b85a6e7 100644
--- a/core/installer.c
+++ b/core/installer.c
@@ -33,6 +33,7 @@ 
 #include "progress.h"
 #include "pctl.h"
 #include "swupdate_vars.h"
+#include "lua_util.h"

 /*
  * function returns:
@@ -478,6 +479,13 @@  void cleanup_files(struct swupdate_cfg *software) {
 	dict_drop_db(&software->bootloader);
 	dict_drop_db(&software->vars);

+	/*
+	 * Drop Lua State if instantiated
+	 */
+	if (software->lua_state) {
+		lua_exit(software->lua_state);
+		software->lua_state = NULL;
+	}
 	if (asprintf(&fn, "%s%s", TMPDIR, BOOT_SCRIPT_SUFFIX) != ENOMEM_ASPRINTF) {
 		remove_sw_file(fn);
 		free(fn);
diff --git a/corelib/lua_interface.c b/corelib/lua_interface.c
index 2bd8e6cf..33be8d3b 100644
--- a/corelib/lua_interface.c
+++ b/corelib/lua_interface.c
@@ -1517,7 +1517,7 @@  int lua_handlers_init(void)
 	return ret;
 }

-lua_State *lua_parser_init(const char *buf, struct dict *bootenv)
+lua_State *lua_init(struct dict *bootenv)
 {
 	lua_State *L = luaL_newstate(); /* opens Lua */

@@ -1533,14 +1533,18 @@  lua_State *lua_parser_init(const char *buf, struct dict *bootenv)
 	luaL_setfuncs(L, l_swupdate_bootenv, 1);
 	lua_pop(L, 1); /* remove unused copy left on stack */

+	return L;
+}
+
+int lua_load_buffer(lua_State *L, const char *buf)
+{
 	if (luaL_loadstring(L, buf) || lua_pcall(L, 0, 0, 0)) {
 		LUAstackDump(L);
-		ERROR("ERROR preparing Lua embedded script in parser");
-		lua_close(L);
-		return NULL;
+		ERROR("ERROR loading Lua code");
+		return 1;
 	}

-	return L;
+	return 0;
 }

 int lua_parser_fn(lua_State *L, const char *fcn, struct img_type *img)
diff --git a/include/lua_util.h b/include/lua_util.h
index 1d00bf82..5f5e67a7 100644
--- a/include/lua_util.h
+++ b/include/lua_util.h
@@ -21,7 +21,8 @@  typedef enum {

 void LUAstackDump (lua_State *L);
 int run_lua_script(const char *script, const char *function, char *parms);
-lua_State *lua_parser_init(const char *buf, struct dict *bootenv);
+lua_State *lua_init(struct dict *bootenv);
+int lua_load_buffer(lua_State *L, const char *buf);
 int lua_parser_fn(lua_State *L, const char *fcn, struct img_type *img);
 int lua_handlers_init(void);

@@ -34,7 +35,7 @@  int lua_notify_progress(lua_State *L);

 int lua_get_swupdate_version(lua_State *L);

-#define lua_parser_exit(L) lua_close((lua_State *)L)
+#define lua_exit(L) lua_close((lua_State *)L)

 #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM == 501
 #define LUA_OK 0
@@ -81,9 +82,10 @@  void luaL_pushresult(luaL_Buffer_52 *B);
 #else

 #define lua_State void
-#define lua_parser_exit(L)
-static inline lua_State *lua_parser_init(const char __attribute__ ((__unused__)) *buf,
-					 struct dict __attribute__ ((__unused__)) *bootenv) { return NULL;}
+#define lua_exit(L)
+static inline lua_State *lua_init(struct dict __attribute__ ((__unused__)) *bootenv) { return NULL;}
+static inline int lua_load_buffer(lua_State __attribute__ ((__unused__)) *L,
+					const char __attribute__ ((__unused__)) *buf) {return 1;}
 static inline int lua_parser_fn(lua_State __attribute__ ((__unused__)) *L,
 			 const char __attribute__ ((__unused__)) *fcn,
 			 struct img_type __attribute__ ((__unused__)) *img) { return -1; }
diff --git a/include/swupdate.h b/include/swupdate.h
index 883bad51..e18de8d3 100644
--- a/include/swupdate.h
+++ b/include/swupdate.h
@@ -59,6 +59,7 @@  struct swupdate_cfg {
 	char mtdblacklist[SWUPDATE_GENERAL_STRING_SIZE];
 	char forced_signer_name[SWUPDATE_GENERAL_STRING_SIZE];
 	char namespace_for_vars[SWUPDATE_GENERAL_STRING_SIZE];
+	void *lua_state;
 	bool syslog_enabled;
 	bool no_downgrading;
 	bool no_reinstalling;
diff --git a/parser/parser.c b/parser/parser.c
index 1d9a38db..3944de64 100644
--- a/parser/parser.c
+++ b/parser/parser.c
@@ -1022,15 +1022,24 @@  static int parser(parsertype p, void *cfg, struct swupdate_cfg *swcfg)
 		swcfg->embscript = get_field_string(p, scriptnode, NULL);
 	}

+	L = lua_init(&swcfg->bootloader);
+
 	if (swcfg->embscript) {
+		if (!L) {
+			ERROR("Required embedded script but no Lua not available");
+			return -1;
+		}
 		if (loglevel >= DEBUGLEVEL)
 			TRACE("Found Lua Software:\n%s", swcfg->embscript);
-		L = lua_parser_init(swcfg->embscript, &swcfg->bootloader);
-		if (!L) {
+		if (lua_load_buffer(L, swcfg->embscript)) {
 			ERROR("Required embedded script that cannot be loaded");
+			lua_close(L);
 			return -1;
 		}
 	}
+
+	swcfg->lua_state = L;
+
 	if (get_hw_revision(&swcfg->hw) < 0) {
 		TRACE("Hardware compatibility not found");
 	}
@@ -1049,9 +1058,6 @@  static int parser(parsertype p, void *cfg, struct swupdate_cfg *swcfg)
 	 */
 	parse_partitions(p, cfg, swcfg, L);

-	if (L)
-		lua_parser_exit(L);
-
 	if (LIST_EMPTY(&swcfg->images) &&
 	    LIST_EMPTY(&swcfg->scripts) &&
 	    LIST_EMPTY(&swcfg->bootloader)) {