sol2: Custom exception Handling

Hey,

Again, after more than extensive 4 hours reading and filtering through the docs and other issues, I’ve got a issue I cant figure out how to do it.

I have some functions that after executed I would like to stop running any script. After researching some things and trying others, the one which actually got solving my problem was throwing an exception to kick off the try and catch of my state::script(string).

	sol::table Walker = lua.create_named_table("Walker");

	Walker.set_function("GoLabel", sol::overload(
		[](std::string Label) {
		pugi::xml_node point = CGUI::m_stGUI->p->cWalker->GetNodeFromLabel(Label);
		if (!point.empty()) {
			CGUI::m_stGUI->p->cWalker->m_CurrentPoint = point;
			throw ScriptException::SE_Stop;
		}
		else {
			throw ScriptException::SE_WalkerNoLabel;
		}
	},
		[](std::string Label, bool stopOnNoPoint) {
		pugi::xml_node point = CGUI::m_stGUI->p->cWalker->GetNodeFromLabel(Label);
		if (!point.empty()) {
			CGUI::m_stGUI->p->cWalker->m_CurrentPoint = point;
			throw ScriptException::SE_Stop;
		}
		else if (stopOnNoPoint) {
			throw ScriptException::SE_WalkerNoLabel;
		}
	}
	));

This is the function I’m calling. I’ve even tryied execute a state::script(string) inside the lambda but the refference would not be there, since this lambdas is inside a Setup function on a ScriptManager class.

This is how I call the scripts:

ScriptException CScriptManager::Do(CScriptBase* script, lua_State * st) {
	script->m_Started = true;
	script->m_Ended = false;
		try {
			auto rn = ((st == nullptr) ? lua : (script->thisThread.state())).script(script->m_Script);
			script->m_Ended = true;
		}
		catch (const sol::error& e) {
			script->m_Ended = true;
			std::string error = e.what();
			p->cLog->Log("Script error: " + error, "SCRIPT");
			script->returnValue = -1;
			return ScriptException::SE_Error;
		}
		catch (ScriptException exc) {
			script->m_Ended = true;
			script->returnValue = -1;
			switch (exc) {
			case ScriptException::SE_Stop:
				break;
			case ScriptException::SE_WalkerNoLabel:
				p->cLog->Log("Script used GoLabel to unknown point, stopping walker", "SCRIPT");
			case ScriptException::SE_WalkerOFF:
				p->cSettings->m_Settings.child("Settings").child("Walker").child("Status").attribute("value") = false;
				p->cGUI->UpdateSettingsTree();
				break;
			}
			return exc;
		}
		return ScriptException::SE_Ok;
}

Ok. The thing is, whenever I throw my ScriptException, it gets translated as a sol::error, with an unknown error and traceback information(SOL_CHECK_ARGUMENTS). Is there a way to bypass this and add a custom exception handling?

Out of this errors, I’ve tryied SOL_EXCEPTIONS_SAFE_PROPAGATION, and a few other solutions, but no success.

Is there a way to inside the lambda stop the execution of the script? I would try sol.script(“do return end”), but since I do not get the sol reference I cant do it. I’ve tryied passing “[this]”,“[sol]”, “[&]”, “[=]”, “[&sol = sol]” and a few others, but seems like I really cant reference a member from that function. I know this is C++ related, but could potentially solve my issue.

Thanks again.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

I’ve took the lua_sethook approach to do the aborting procedure on infinite loops. Just in case someone want to use it, i’m doing it this way:

    lua::state thisState;
    lua_sethook(thisState.lua_state(), &InfiniteLoop, LUA_MASKCOUNT, 100);
    lua_sethook(thisState.lua_state(), &ForceKill, LUA_MASKLINE, 0);

void InfiniteLoop(lua_State* argst, lua_Debug * argdb) {
	luaL_error(argst, "Reached the script execution amount.");
};
void ForceKill(lua_State* argst, lua_Debug * argdb) {
	if (cScripts->m_Resetting) {
		luaL_error(argst, "Script killed.");
	}
};

Thanks @ThePhD

Throwing strings themselves is a bad, bad idea…

… But! You’re free to do as you wish.