summaryrefslogtreecommitdiffstats
path: root/player/lua.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-19 05:46:16 +0200
committerwm4 <wm4@nowhere>2014-10-19 05:51:37 +0200
commitff029cb4cfae6e9984821d5f9c9dd49c2d566f96 (patch)
treeb1221d0b82c5a3684c8386eff56e50da43c9c495 /player/lua.c
parent5548c75e5507da6a0f9fb6a45a07a5cc6edd9393 (diff)
downloadmpv-ff029cb4cfae6e9984821d5f9c9dd49c2d566f96.tar.bz2
mpv-ff029cb4cfae6e9984821d5f9c9dd49c2d566f96.tar.xz
lua: strictly free memory on errors
Thanks to the recently introduced mp_lua_PITA(), this is "simple" now. It fixes leaks on Lua errors. The hack to avoid stack overflows manually isn't needed anymore, and the Lua error handler will take care of this.
Diffstat (limited to 'player/lua.c')
-rw-r--r--player/lua.c55
1 files changed, 26 insertions, 29 deletions
diff --git a/player/lua.c b/player/lua.c
index 306f3a66f5..b9ac756bf1 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -106,6 +106,9 @@ static int destroy_crap(lua_State *L)
// This can be used to free temporary C data structures correctly if Lua errors
// happen.
// You can't free the talloc context directly; the Lua __gc handler does this.
+// In my cases, talloc_free_children(returnval) will be used to free attached
+// memory in advance when it's known not to be needed anymore (a minor
+// optimization). Freeing it completely must be left to the Lua GC.
static void *mp_lua_PITA(lua_State *L)
{
void **data = lua_newuserdata(L, sizeof(void *)); // u
@@ -120,6 +123,12 @@ static void *mp_lua_PITA(lua_State *L)
return *data;
}
+// Perform the equivalent of mpv_free_node_contents(node) when tmp is freed.
+static void auto_free_node(void *tmp, mpv_node *node)
+{
+ talloc_steal(tmp, node_get_alloc(node));
+}
+
static struct script_ctx *get_ctx(lua_State *L)
{
lua_getfield(L, LUA_REGISTRYINDEX, "ctx");
@@ -450,7 +459,7 @@ static int script_resume_all(lua_State *L)
return 0;
}
-static bool pushnode(lua_State *L, mpv_node *node, int depth);
+static void pushnode(lua_State *L, mpv_node *node);
static int script_wait_event(lua_State *L)
{
@@ -517,8 +526,7 @@ static int script_wait_event(lua_State *L)
lua_setfield(L, -2, "name");
switch (prop->format) {
case MPV_FORMAT_NODE:
- if (!pushnode(L, prop->data, 50))
- luaL_error(L, "stack overflow");
+ pushnode(L, prop->data);
break;
case MPV_FORMAT_DOUBLE:
lua_pushnumber(L, *(double *)prop->data);
@@ -815,11 +823,8 @@ static int script_get_property_number(lua_State *L)
}
}
-static bool pushnode(lua_State *L, mpv_node *node, int depth)
+static void pushnode(lua_State *L, mpv_node *node)
{
- depth--;
- if (depth < 0)
- return false;
luaL_checkstack(L, 6, "stack overflow");
switch (node->format) {
@@ -843,8 +848,7 @@ static bool pushnode(lua_State *L, mpv_node *node, int depth)
lua_getfield(L, LUA_REGISTRYINDEX, "ARRAY"); // table mt
lua_setmetatable(L, -2); // table
for (int n = 0; n < node->u.list->num; n++) {
- if (!pushnode(L, &node->u.list->values[n], depth)) // table value
- return false;
+ pushnode(L, &node->u.list->values[n]); // table value
lua_rawseti(L, -2, n + 1); // table
}
break;
@@ -854,8 +858,7 @@ static bool pushnode(lua_State *L, mpv_node *node, int depth)
lua_setmetatable(L, -2); // table
for (int n = 0; n < node->u.list->num; n++) {
lua_pushstring(L, node->u.list->keys[n]); // table key
- if (!pushnode(L, &node->u.list->values[n], depth)) // table key value
- return false;
+ pushnode(L, &node->u.list->values[n]); // table key value
lua_rawset(L, -3);
}
break;
@@ -867,26 +870,24 @@ static bool pushnode(lua_State *L, mpv_node *node, int depth)
lua_setmetatable(L, -2); // table
break;
}
- return true;
}
static int script_get_property_native(lua_State *L)
{
struct script_ctx *ctx = get_ctx(L);
const char *name = luaL_checkstring(L, 1);
+ void *tmp = mp_lua_PITA(L);
mpv_node node;
int err = mpv_get_property(ctx->client, name, MPV_FORMAT_NODE, &node);
- const char *errstr = mpv_error_string(err);
if (err >= 0) {
- bool ok = pushnode(L, &node, 50);
- mpv_free_node_contents(&node);
- if (ok)
- return 1;
- errstr = "value too large";
+ auto_free_node(tmp, &node);
+ pushnode(L, &node);
+ talloc_free_children(tmp);
+ return 1;
}
lua_pushvalue(L, 2);
- lua_pushstring(L, errstr);
+ lua_pushstring(L, mpv_error_string(err));
return 2;
}
@@ -931,17 +932,14 @@ static int script_command_native(lua_State *L)
void *tmp = mp_lua_PITA(L);
makenode(tmp, &node, L, 1);
int err = mpv_command_node(ctx->client, &node, &result);
- talloc_free_children(tmp);
- const char *errstr = mpv_error_string(err);
if (err >= 0) {
- bool ok = pushnode(L, &result, 50);
- mpv_free_node_contents(&result);
- if (ok)
- return 1;
- errstr = "command result too large";
+ auto_free_node(tmp, &result);
+ pushnode(L, &result);
+ talloc_free_children(tmp);
+ return 1;
}
lua_pushvalue(L, 2);
- lua_pushstring(L, errstr);
+ lua_pushstring(L, mpv_error_string(err));
return 2;
}
@@ -1303,8 +1301,7 @@ static int script_parse_json(lua_State *L)
ok = !text[0] || !trail;
}
if (ok) {
- if (!pushnode(L, &node, 64))
- luaL_error(L, "stack overflow");
+ pushnode(L, &node);
lua_pushnil(L);
} else {
lua_pushnil(L);