← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3006: make Lua stack handling re-entrant (possible to inject messages from Lua which themselves trigger...

 

------------------------------------------------------------
revno: 3006
committer: cologic <ne5@xxxxxxxxxxx>
branch nick: dcplusplus
timestamp: Fri 2012-07-20 04:28:15 -0400
message:
  make Lua stack handling re-entrant (possible to inject messages from Lua which themselves trigger Lua handling)
modified:
  plugins/Script/ScriptInstance.cpp
  plugins/Script/ScriptInstance.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'plugins/Script/ScriptInstance.cpp'
--- plugins/Script/ScriptInstance.cpp	2012-07-19 23:07:17 +0000
+++ plugins/Script/ScriptInstance.cpp	2012-07-20 08:28:15 +0000
@@ -27,21 +27,27 @@
 CriticalSection ScriptInstance::cs;
 
 bool ScriptInstance::MakeCallRaw(const string& table, const string& method, int args, int ret) throw() {
+	auto stack_pre = lua_gettop(L) - args;
 	lua_getglobal(L, table.c_str());		// args + 1
-	lua_pushstring(L, method.c_str());		// args + 2
-	if (lua_istable(L, -2)) {
+	if (lua_istable(L, -1)) {
+		lua_pushstring(L, method.c_str());	// args + 2
 		lua_gettable(L, -2);				// args + 2
 		lua_remove(L, -2);					// args + 1
-		lua_insert(L, 1);					// args + 1
+		lua_insert(L, stack_pre + 1);		// args + 1
 		if(lua_pcall(L, args, ret, 0) == 0) {
+			dcassert(lua_gettop(L) - stack_pre == ret);
 			return true;
 		}
 		const char *msg = lua_tostring(L, -1);
-		Util::logMessage((msg != NULL) ? string("Lua Error: ") + msg : string("Lua Error: (unknown)"));
+		Util::logMessage((msg != NULL) ? string("Lua Error calling ") + table + "." + method + ": " + msg : string("Lua Error: (unknown)"));
 		lua_pop(L, 1);
 	} else {
-		lua_settop(L, 0);
+		// Abandon to garbage collector arguments pushed to function in table
+		// that doesn't exist, up to point in stack where this instance of Lua
+		// (in a possibly re-entrant manner) started building.
+		lua_settop(L, stack_pre);
 	}
+	dcassert(lua_gettop(L) == stack_pre);
 	return false;
 }
 

=== modified file 'plugins/Script/ScriptInstance.h'
--- plugins/Script/ScriptInstance.h	2012-07-19 22:01:31 +0000
+++ plugins/Script/ScriptInstance.h	2012-07-20 08:28:15 +0000
@@ -42,7 +42,6 @@
 	template <typename T>
 	bool MakeCall(const string& table, const string& method, int ret, const T& t) throw() {
 		Lock l(cs);
-		dcassert(lua_gettop(L) == 0);
 		LuaPush(t);
 		return MakeCallRaw(table, method, 1, ret);
 	}
@@ -50,7 +49,6 @@
 	template <typename T, typename T2>
 	bool MakeCall(const string& table, const string& method, int ret, const T& t, const T2& t2) throw() {
 		Lock l(cs);
-		dcassert(lua_gettop(L) == 0);
 		LuaPush(t);
 		LuaPush(t2);
 		return MakeCallRaw(table, method, 2, ret);