Skip to content

Commit 3304e1e

Browse files
kahrlest31
authored andcommittedAug 26, 2015
Push error handler afresh each time lua_pcall is used
Fixes "double fault" / "error in error handling" messages (issue #1423) and instead shows a complete backtrace.
1 parent 8658c8d commit 3304e1e

16 files changed

+188
-92
lines changed
 

Diff for: ‎src/script/common/c_internal.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -136,28 +136,28 @@ void script_run_callbacks_f(lua_State *L, int nargs,
136136
FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments");
137137

138138
// Insert error handler
139-
lua_pushcfunction(L, script_error_handler);
140-
int errorhandler = lua_gettop(L) - nargs - 1;
141-
lua_insert(L, errorhandler);
139+
PUSH_ERROR_HANDLER(L);
140+
int error_handler = lua_gettop(L) - nargs - 1;
141+
lua_insert(L, error_handler);
142142

143143
// Insert run_callbacks between error handler and table
144144
lua_getglobal(L, "core");
145145
lua_getfield(L, -1, "run_callbacks");
146146
lua_remove(L, -2);
147-
lua_insert(L, errorhandler + 1);
147+
lua_insert(L, error_handler + 1);
148148

149149
// Insert mode after table
150150
lua_pushnumber(L, (int) mode);
151-
lua_insert(L, errorhandler + 3);
151+
lua_insert(L, error_handler + 3);
152152

153153
// Stack now looks like this:
154154
// ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
155155

156-
int result = lua_pcall(L, nargs + 2, 1, errorhandler);
156+
int result = lua_pcall(L, nargs + 2, 1, error_handler);
157157
if (result != 0)
158158
script_error(L, result, NULL, fxn);
159159

160-
lua_remove(L, -2); // Remove error handler
160+
lua_remove(L, error_handler);
161161
}
162162

163163
void log_deprecated(lua_State *L, const std::string &message)

Diff for: ‎src/script/common/c_internal.h

+4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ extern "C" {
5353
#define CUSTOM_RIDX_SCRIPTAPI (CUSTOM_RIDX_BASE)
5454
#define CUSTOM_RIDX_GLOBALS_BACKUP (CUSTOM_RIDX_BASE + 1)
5555
#define CUSTOM_RIDX_CURRENT_MOD_NAME (CUSTOM_RIDX_BASE + 2)
56+
#define CUSTOM_RIDX_ERROR_HANDLER (CUSTOM_RIDX_BASE + 3)
5657

58+
// Pushes the error handler onto the stack and returns its index
59+
#define PUSH_ERROR_HANDLER(L) \
60+
(lua_rawgeti((L), LUA_REGISTRYINDEX, CUSTOM_RIDX_ERROR_HANDLER), lua_gettop((L)))
5761

5862
#define PCALL_RESL(L, RES) do { \
5963
int result_ = (RES); \

Diff for: ‎src/script/cpp_api/s_async.cpp

+8-5
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ void AsyncEngine::putJobResult(LuaJobInfo result)
144144
}
145145

146146
/******************************************************************************/
147-
void AsyncEngine::step(lua_State *L, int errorhandler)
147+
void AsyncEngine::step(lua_State *L)
148148
{
149+
int error_handler = PUSH_ERROR_HANDLER(L);
149150
lua_getglobal(L, "core");
150151
resultQueueMutex.lock();
151152
while (!resultQueue.empty()) {
@@ -164,10 +165,10 @@ void AsyncEngine::step(lua_State *L, int errorhandler)
164165
lua_pushlstring(L, jobDone.serializedResult.data(),
165166
jobDone.serializedResult.size());
166167

167-
PCALL_RESL(L, lua_pcall(L, 2, 0, errorhandler));
168+
PCALL_RESL(L, lua_pcall(L, 2, 0, error_handler));
168169
}
169170
resultQueueMutex.unlock();
170-
lua_pop(L, 1); // Pop core
171+
lua_pop(L, 2); // Pop core and error handler
171172
}
172173

173174
/******************************************************************************/
@@ -248,6 +249,8 @@ void* AsyncWorkerThread::run()
248249
abort();
249250
}
250251

252+
int error_handler = PUSH_ERROR_HANDLER(L);
253+
251254
lua_getglobal(L, "core");
252255
if (lua_isnil(L, -1)) {
253256
errorstream << "Unable to find core within async environment!";
@@ -279,7 +282,7 @@ void* AsyncWorkerThread::run()
279282
toProcess.serializedParams.data(),
280283
toProcess.serializedParams.size());
281284

282-
int result = lua_pcall(L, 2, 1, m_errorhandler);
285+
int result = lua_pcall(L, 2, 1, error_handler);
283286
if (result) {
284287
PCALL_RES(result);
285288
toProcess.serializedResult = "";
@@ -296,7 +299,7 @@ void* AsyncWorkerThread::run()
296299
jobDispatcher->putJobResult(toProcess);
297300
}
298301

299-
lua_pop(L, 1); // Pop core
302+
lua_pop(L, 2); // Pop core and error handler
300303

301304
return 0;
302305
}

Diff for: ‎src/script/cpp_api/s_async.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,8 @@ class AsyncEngine {
9595
* Engine step to process finished jobs
9696
* the engine step is one way to pass events back, PushFinishedJobs another
9797
* @param L The Lua stack
98-
* @param errorhandler Stack index of the Lua error handler
9998
*/
100-
void step(lua_State *L, int errorhandler);
99+
void step(lua_State *L);
101100

102101
/**
103102
* Push a list of finished jobs onto the stack

Diff for: ‎src/script/cpp_api/s_base.cpp

+16-14
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ ScriptApiBase::ScriptApiBase()
7878

7979
luaL_openlibs(m_luastack);
8080

81-
// Add and save an error handler
82-
lua_pushcfunction(m_luastack, script_error_handler);
83-
m_errorhandler = lua_gettop(m_luastack);
84-
8581
// Make the ScriptApiBase* accessible to ModApiBase
8682
lua_pushlightuserdata(m_luastack, this);
8783
lua_rawseti(m_luastack, LUA_REGISTRYINDEX, CUSTOM_RIDX_SCRIPTAPI);
8884

85+
// Add and save an error handler
86+
lua_pushcfunction(m_luastack, script_error_handler);
87+
lua_rawseti(m_luastack, LUA_REGISTRYINDEX, CUSTOM_RIDX_ERROR_HANDLER);
88+
8989
// If we are using LuaJIT add a C++ wrapper function to catch
9090
// exceptions thrown in Lua -> C++ calls
9191
#if USE_LUAJIT
@@ -133,13 +133,15 @@ bool ScriptApiBase::loadScript(const std::string &script_path, std::string *erro
133133

134134
lua_State *L = getStack();
135135

136+
int error_handler = PUSH_ERROR_HANDLER(L);
137+
136138
bool ok;
137139
if (m_secure) {
138140
ok = ScriptApiSecurity::safeLoadFile(L, script_path.c_str());
139141
} else {
140142
ok = !luaL_loadfile(L, script_path.c_str());
141143
}
142-
ok = ok && !lua_pcall(L, 0, 0, m_errorhandler);
144+
ok = ok && !lua_pcall(L, 0, 0, error_handler);
143145
if (!ok) {
144146
std::string error_msg = lua_tostring(L, -1);
145147
if (error)
@@ -150,9 +152,9 @@ bool ScriptApiBase::loadScript(const std::string &script_path, std::string *erro
150152
<< error_msg << std::endl << std::endl
151153
<< "======= END OF ERROR FROM LUA ========" << std::endl;
152154
lua_pop(L, 1); // Pop error message from stack
153-
return false;
154155
}
155-
return true;
156+
lua_pop(L, 1); // Pop error handler
157+
return ok;
156158
}
157159

158160
// Push the list of callbacks (a lua table).
@@ -168,28 +170,28 @@ void ScriptApiBase::runCallbacksRaw(int nargs,
168170
FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments");
169171

170172
// Insert error handler
171-
lua_pushcfunction(L, script_error_handler);
172-
int errorhandler = lua_gettop(L) - nargs - 1;
173-
lua_insert(L, errorhandler);
173+
PUSH_ERROR_HANDLER(L);
174+
int error_handler = lua_gettop(L) - nargs - 1;
175+
lua_insert(L, error_handler);
174176

175177
// Insert run_callbacks between error handler and table
176178
lua_getglobal(L, "core");
177179
lua_getfield(L, -1, "run_callbacks");
178180
lua_remove(L, -2);
179-
lua_insert(L, errorhandler + 1);
181+
lua_insert(L, error_handler + 1);
180182

181183
// Insert mode after table
182184
lua_pushnumber(L, (int)mode);
183-
lua_insert(L, errorhandler + 3);
185+
lua_insert(L, error_handler + 3);
184186

185187
// Stack now looks like this:
186188
// ... <error handler> <run_callbacks> <table> <mode> <arg#1> <arg#2> ... <arg#n>
187189

188-
int result = lua_pcall(L, nargs + 2, 1, errorhandler);
190+
int result = lua_pcall(L, nargs + 2, 1, error_handler);
189191
if (result != 0)
190192
scriptError(result, fxn);
191193

192-
lua_remove(L, -2); // Remove error handler
194+
lua_remove(L, error_handler);
193195
}
194196

195197
void ScriptApiBase::realityCheck()

Diff for: ‎src/script/cpp_api/s_base.h

-2
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,6 @@ class ScriptApiBase {
109109

110110
Mutex m_luastackmutex;
111111
std::string m_last_run_mod;
112-
// Stack index of Lua error handler
113-
int m_errorhandler;
114112
bool m_secure;
115113
#ifdef SCRIPTAPI_LOCK_DEBUG
116114
bool m_locked;

Diff for: ‎src/script/cpp_api/s_entity.cpp

+21-10
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ void ScriptApiEntity::luaentity_Activate(u16 id,
8080

8181
verbosestream << "scriptapi_luaentity_activate: id=" << id << std::endl;
8282

83+
int error_handler = PUSH_ERROR_HANDLER(L);
84+
8385
// Get core.luaentities[id]
8486
luaentity_get(L, id);
8587
int object = lua_gettop(L);
@@ -93,11 +95,11 @@ void ScriptApiEntity::luaentity_Activate(u16 id,
9395
lua_pushinteger(L, dtime_s);
9496

9597
setOriginFromTable(object);
96-
PCALL_RES(lua_pcall(L, 3, 0, m_errorhandler));
98+
PCALL_RES(lua_pcall(L, 3, 0, error_handler));
9799
} else {
98100
lua_pop(L, 1);
99101
}
100-
lua_pop(L, 1); // Pop object
102+
lua_pop(L, 2); // Pop object and error handler
101103
}
102104

103105
void ScriptApiEntity::luaentity_Remove(u16 id)
@@ -126,6 +128,8 @@ std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
126128

127129
//infostream<<"scriptapi_luaentity_get_staticdata: id="<<id<<std::endl;
128130

131+
int error_handler = PUSH_ERROR_HANDLER(L);
132+
129133
// Get core.luaentities[id]
130134
luaentity_get(L, id);
131135
int object = lua_gettop(L);
@@ -140,9 +144,10 @@ std::string ScriptApiEntity::luaentity_GetStaticdata(u16 id)
140144
lua_pushvalue(L, object); // self
141145

142146
setOriginFromTable(object);
143-
PCALL_RES(lua_pcall(L, 1, 1, m_errorhandler));
147+
PCALL_RES(lua_pcall(L, 1, 1, error_handler));
144148

145-
lua_remove(L, object); // Remove object
149+
lua_remove(L, object);
150+
lua_remove(L, error_handler);
146151

147152
size_t len = 0;
148153
const char *s = lua_tolstring(L, -1, &len);
@@ -196,6 +201,8 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
196201

197202
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
198203

204+
int error_handler = PUSH_ERROR_HANDLER(L);
205+
199206
// Get core.luaentities[id]
200207
luaentity_get(L, id);
201208
int object = lua_gettop(L);
@@ -211,9 +218,9 @@ void ScriptApiEntity::luaentity_Step(u16 id, float dtime)
211218
lua_pushnumber(L, dtime); // dtime
212219

213220
setOriginFromTable(object);
214-
PCALL_RES(lua_pcall(L, 2, 0, m_errorhandler));
221+
PCALL_RES(lua_pcall(L, 2, 0, error_handler));
215222

216-
lua_pop(L, 1); // Pop object
223+
lua_pop(L, 2); // Pop object and error handler
217224
}
218225

219226
// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch,
@@ -226,6 +233,8 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
226233

227234
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
228235

236+
int error_handler = PUSH_ERROR_HANDLER(L);
237+
229238
// Get core.luaentities[id]
230239
luaentity_get(L,id);
231240
int object = lua_gettop(L);
@@ -244,9 +253,9 @@ void ScriptApiEntity::luaentity_Punch(u16 id,
244253
push_v3f(L, dir);
245254

246255
setOriginFromTable(object);
247-
PCALL_RES(lua_pcall(L, 5, 0, m_errorhandler));
256+
PCALL_RES(lua_pcall(L, 5, 0, error_handler));
248257

249-
lua_pop(L, 1); // Pop object
258+
lua_pop(L, 2); // Pop object and error handler
250259
}
251260

252261
// Calls entity:on_rightclick(ObjectRef clicker)
@@ -257,6 +266,8 @@ void ScriptApiEntity::luaentity_Rightclick(u16 id,
257266

258267
//infostream<<"scriptapi_luaentity_step: id="<<id<<std::endl;
259268

269+
int error_handler = PUSH_ERROR_HANDLER(L);
270+
260271
// Get core.luaentities[id]
261272
luaentity_get(L, id);
262273
int object = lua_gettop(L);
@@ -272,8 +283,8 @@ void ScriptApiEntity::luaentity_Rightclick(u16 id,
272283
objectrefGetOrCreate(L, clicker); // Clicker reference
273284

274285
setOriginFromTable(object);
275-
PCALL_RES(lua_pcall(L, 2, 0, m_errorhandler));
286+
PCALL_RES(lua_pcall(L, 2, 0, error_handler));
276287

277-
lua_pop(L, 1); // Pop object
288+
lua_pop(L, 2); // Pop object and error handler
278289
}
279290

0 commit comments

Comments
 (0)
Please sign in to comment.