From 43fea45f9f54318051f1d527bb8969adadaf2749 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 12 Mar 2017 13:20:35 -0300 Subject: [PATCH] =?UTF-8?q?Fix=20a=20memory=20leak=20when=20pushing=20love?= =?UTF-8?q?=20objects=20to=20threads=20which=20never=20load=20that=20objec?= =?UTF-8?q?t=E2=80=99s=20module=20(resolves=20issue=20#1267).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also fix Variant assignment operator to call release() on the correct object. --HG-- branch : minor --- src/common/Variant.cpp | 10 +++++----- src/common/runtime.cpp | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/common/Variant.cpp b/src/common/Variant.cpp index 16200c64b..8631de593 100644 --- a/src/common/Variant.cpp +++ b/src/common/Variant.cpp @@ -106,7 +106,7 @@ Variant::Variant(const Variant &v) { if (type == STRING) data.string->retain(); - else if (type == FUSERDATA && data.userdata != nullptr) + else if (type == FUSERDATA && udatatype != nullptr && data.userdata != nullptr) ((love::Object *) data.userdata)->retain(); else if (type == TABLE) data.table->retain(); @@ -128,7 +128,7 @@ Variant::~Variant() data.string->release(); break; case FUSERDATA: - if (data.userdata != nullptr) + if (udatatype != nullptr && data.userdata != nullptr) ((love::Object *) data.userdata)->release(); break; case TABLE: @@ -143,15 +143,15 @@ Variant &Variant::operator = (const Variant &v) { if (v.type == STRING) v.data.string->retain(); - else if (v.type == FUSERDATA && v.data.userdata != nullptr) + else if (v.type == FUSERDATA && v.udatatype != nullptr && v.data.userdata != nullptr) ((love::Object *) v.data.userdata)->retain(); else if (v.type == TABLE) v.data.table->retain(); if (type == STRING) data.string->release(); - else if (type == FUSERDATA && v.data.userdata != nullptr) - ((love::Object *) v.data.userdata)->release(); + else if (type == FUSERDATA && udatatype != nullptr && data.userdata != nullptr) + ((love::Object *) data.userdata)->release(); else if (type == TABLE) data.table->release(); diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index b843e8fcb..9526eed0f 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -490,6 +490,19 @@ void luax_rawnewtype(lua_State *L, love::Type &type, love::Object *object) const char *name = type.getName(); luaL_newmetatable(L, name); + + lua_getfield(L, -1, "__gc"); + bool has_gc = !lua_isnoneornil(L, -1); + lua_pop(L, 1); + + // Make sure mt.__gc exists, so Lua states which don't have the object's + // module loaded will still clean the object up when it's collected. + if (!has_gc) + { + lua_pushcfunction(L, w__gc); + lua_setfield(L, -2, "__gc"); + } + lua_setmetatable(L, -2); }