Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 330a959

Browse files
committed
[[ Bug 23240 ]] Fix engine lockup after error in modal stack
This patch fixes an infinite loop that occurs when the "traceError" message is sent and not handled. By returning false from MCB_error when the message is not handled, the while loops in MCExecContext::TryToEvaluate* methods will exit
1 parent eeb23f2 commit 330a959

File tree

2 files changed

+48
-33
lines changed

2 files changed

+48
-33
lines changed

engine/src/debug.cpp

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,10 @@ void MCB_setmsg(MCExecContext &ctxt, MCStringRef p_string)
192192

193193
}
194194

195-
void MCB_message(MCExecContext &ctxt, MCNameRef mess, MCParameter *p)
195+
Exec_stat MCB_message(MCExecContext &ctxt, MCNameRef mess, MCParameter *p)
196196
{
197+
Exec_stat t_stat = ES_NOT_HANDLED;
198+
197199
Boolean exitall = MCexitall;
198200
MCSaveprops sp;
199201
MCU_saveprops(sp);
@@ -208,8 +210,8 @@ void MCB_message(MCExecContext &ctxt, MCNameRef mess, MCParameter *p)
208210
/* UNCHECKED */ MCVariable::createwithname(MCNAME("MCdebugresult"), MCresult);
209211
MCtracereturn = False;
210212
MCtraceabort = False;
211-
212-
MCExecResultMode t_oldresultmode = MCresultmode;
213+
214+
MCExecResultMode t_oldresultmode = MCresultmode;
213215

214216
Boolean oldcheck;
215217
oldcheck = MCcheckstack;
@@ -220,19 +222,21 @@ void MCB_message(MCExecContext &ctxt, MCNameRef mess, MCParameter *p)
220222

221223
// OK-2008-11-28: [[Bug 7491]] - It seems that using the "send" parameter causes problems with the MetaCard debugger
222224
// So instead of doing that, I've added a new optional parameter to MCObject::send, called p_force, and used this instead.
223-
if (ctxt.GetObject() -> message(mess, p, True, False, True) == ES_NORMAL)
225+
226+
t_stat = ctxt.GetObject() -> message(mess, p, True, False, True);
227+
if (t_stat == ES_NORMAL)
224228
{
225229
MCcheckstack = oldcheck;
226230

227-
while (!MCtracereturn)
231+
while (!MCtracereturn)
228232
{
229233
MCU_resetprops(True);
230234
MCscreen->wait(REFRESH_INTERVAL, True, True);
231235
}
232236

233-
if (!MCtracedobject)
237+
if (!MCtracedobject)
234238
MCtracedobject = ctxt.GetObject();
235-
239+
236240
if (MCtraceabort)
237241
{
238242
MCtraceabort = False;
@@ -241,19 +245,22 @@ void MCB_message(MCExecContext &ctxt, MCNameRef mess, MCParameter *p)
241245
else
242246
if (MCtracestackptr)
243247
MCtrace = True;
244-
}
245-
MCcheckstack = oldcheck;
246-
MCtracewindow = NULL;
247-
delete MCresult;
248-
MCresult = oldresult;
249-
MCU_restoreprops(sp);
250-
MCexitall = exitall;
251-
MCresultmode = t_oldresultmode;
252-
248+
}
249+
MCcheckstack = oldcheck;
250+
MCtracewindow = NULL;
251+
delete MCresult;
252+
MCresult = oldresult;
253+
MCU_restoreprops(sp);
254+
MCexitall = exitall;
255+
MCresultmode = t_oldresultmode;
256+
257+
return t_stat;
253258
}
254259

255-
void MCB_prepmessage(MCExecContext &ctxt, MCNameRef mess, uint2 line, uint2 pos, uint2 id, MCStringRef p_info)
260+
Exec_stat MCB_prepmessage(MCExecContext &ctxt, MCNameRef mess, uint2 line, uint2 pos, uint2 id, MCStringRef p_info)
256261
{
262+
Exec_stat t_stat = ES_NOT_HANDLED;
263+
257264
Boolean added = False;
258265
if (MCnexecutioncontexts < MAX_CONTEXTS)
259266
{
@@ -276,22 +283,26 @@ void MCB_prepmessage(MCExecContext &ctxt, MCNameRef mess, uint2 line, uint2 pos,
276283
ctxt.GetObject()->names(P_LONG_ID, &t_val);
277284
MCeerror->add(EE_OBJECT_NAME, 0, 0, *t_val);
278285

279-
MCAutoStringRef t_error;
280-
MCeerror -> copyasstringref(&t_error);
281-
p4.setvalueref_argument(*t_error);
286+
MCAutoStringRef t_error;
287+
MCeerror -> copyasstringref(&t_error);
288+
p4.setvalueref_argument(*t_error);
282289
}
283290
else if (!MCStringIsEmpty(p_info))
284291
{
285292
p3.setnext(&p4);
286293
p4.setvalueref_argument(p_info);
287294
}
288-
MCDeletedObjectsFreezePool();
289-
MCB_message(ctxt, mess, &p1);
290-
MCDeletedObjectsThawPool();
295+
296+
MCDeletedObjectsFreezePool();
297+
t_stat = MCB_message(ctxt, mess, &p1);
298+
MCDeletedObjectsThawPool();
299+
291300
if (id != 0)
292301
MCeerror->clear();
293302
if (added)
294303
MCnexecutioncontexts--;
304+
305+
return t_stat;
295306
}
296307

297308
void MCB_trace(MCExecContext &ctxt, uint2 line, uint2 pos)
@@ -337,19 +348,23 @@ bool s_in_trace_error = false;
337348

338349
bool MCB_error(MCExecContext &ctxt, uint2 line, uint2 pos, uint2 id)
339350
{
340-
// An unhandled error has been thrown - end all modal loops
341-
MCscreen->breakModalLoops();
342-
343-
// OK-2009-03-25: [[Bug 7517]] - The crash described in this bug report is probably caused by a stack overflow. This overflow is due to
351+
// An unhandled error has been thrown - end all modal loops
352+
MCscreen->breakModalLoops();
353+
354+
// OK-2009-03-25: [[Bug 7517]] - The crash described in this bug report is probably caused by a stack overflow. This overflow is due to
344355
// errors being thrown in the IDE (or in this case GLX2) component of the debugger. This should prevent traceError from recursing.
345356
if (s_in_trace_error)
346357
return false;
347-
358+
359+
360+
// MCB_error should not be called again if 'traceError' was not handled
361+
bool t_handled;
348362
s_in_trace_error = true;
349-
MCB_prepmessage(ctxt, MCM_trace_error, line, pos, id);
350-
MCerrorlock++; // suppress errors as stack unwinds
363+
t_handled = MCB_prepmessage(ctxt, MCM_trace_error, line, pos, id) == ES_NORMAL;
351364
s_in_trace_error = false;
352-
return true;
365+
MCerrorlock++; // suppress errors as stack unwinds
366+
367+
return t_handled;
353368
}
354369

355370
void MCB_done(MCExecContext &ctxt)

engine/src/debug.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ extern MCNameRef MClogmessage;
102102
struct MCExecValue;
103103

104104
extern void MCB_setmsg(MCExecContext &ctxt, MCStringRef p_string);
105-
extern void MCB_message(MCExecContext &ctxt, MCNameRef message, MCParameter *p);
106-
extern void MCB_prepmessage(MCExecContext &ctxt, MCNameRef message, uint2 line, uint2 pos, uint2 id, MCStringRef p_info = kMCEmptyString);
105+
extern Exec_stat MCB_message(MCExecContext &ctxt, MCNameRef message, MCParameter *p);
106+
extern Exec_stat MCB_prepmessage(MCExecContext &ctxt, MCNameRef message, uint2 line, uint2 pos, uint2 id, MCStringRef p_info = kMCEmptyString);
107107
extern void MCB_break(MCExecContext &ctxt, uint2 line, uint2 pos);
108108
extern void MCB_trace(MCExecContext &ctxt, uint2 line, uint2 pos);
109109
extern bool MCB_error(MCExecContext &ctxt, uint2 line, uint2 pos, uint2 id);

0 commit comments

Comments
 (0)