From cb84aa19c45aac2d527404dc4a0a683f6102ab9f Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Tue, 14 Jun 2011 17:02:07 +0200 Subject: Lua exceptions can now outlive thier lua context --- src/FbTk/Luamm.cc | 9 +++++---- src/FbTk/Luamm.hh | 14 +++++++++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/FbTk/Luamm.cc b/src/FbTk/Luamm.cc index c4ea2e0..563be9c 100644 --- a/src/FbTk/Luamm.cc +++ b/src/FbTk/Luamm.cc @@ -173,7 +173,7 @@ namespace lua { } exception::exception(state *l) - : std::runtime_error(get_error_msg(l)), L(l) + : std::runtime_error(get_error_msg(l)), L(l), L_valid(l->get_valid()) { L->checkstack(1); @@ -184,7 +184,7 @@ namespace lua { } exception::exception(const exception &other) - : std::runtime_error(other), L(other.L) + : std::runtime_error(other), L(other.L), L_valid(other.L_valid) { L->checkstack(2); @@ -196,7 +196,7 @@ namespace lua { exception::~exception() throw() { - if(not L) + if(not L or not *L_valid) return; L->checkstack(1); @@ -217,7 +217,7 @@ namespace lua { } state::state() - : cobj(luaL_newstate()) + : cobj(luaL_newstate()), valid(new bool(true)) { if(cobj == NULL) { // docs say this can happen only in case of a memory allocation error @@ -249,6 +249,7 @@ namespace lua { luaL_openlibs(cobj); } catch(...) { + *valid = false; lua_close(cobj); throw; } diff --git a/src/FbTk/Luamm.hh b/src/FbTk/Luamm.hh index f2084e7..1ba9cbe 100644 --- a/src/FbTk/Luamm.hh +++ b/src/FbTk/Luamm.hh @@ -31,6 +31,7 @@ #include #include +#include "RefCount.hh" #include "Slot.hh" namespace lua { @@ -84,6 +85,7 @@ namespace lua { */ class exception: public std::runtime_error { state *L; + FbTk::RefCount L_valid; int key; static std::string get_error_msg(state *L); @@ -152,9 +154,19 @@ namespace lua { bool safe_compare(lua_CFunction trampoline, int index1, int index2); void do_pushclosure(int n); + /** + * The pointed-to value is true if this object still exists. We need this because the + * exceptions have to know if they may reference it to remove the saved lua exception. If + * this object is destroyed then the exception was already collected by the garbage + * colletor and referencing this would generate a segfault. + */ + FbTk::RefCount valid; + public: state(); - ~state() { lua_close(cobj); } + ~state() { *valid = false; lua_close(cobj); } + + FbTk::RefCount get_valid() const { return valid; } /* * Lua functions come in three flavours -- cgit v0.11.2