Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/VM/src/ldo.cpp
2725 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
3
#include "ldo.h"
4
5
#include "lstring.h"
6
#include "lfunc.h"
7
#include "lgc.h"
8
#include "lmem.h"
9
#include "lvm.h"
10
11
#if LUA_USE_LONGJMP
12
#include <setjmp.h>
13
#include <stdlib.h>
14
#else
15
#include <stdexcept>
16
#endif
17
18
#include <string.h>
19
20
LUAU_FASTFLAGVARIABLE(LuauStacklessPcall)
21
22
// keep max stack allocation request under 1GB
23
#define MAX_STACK_SIZE (int(1024 / sizeof(TValue)) * 1024 * 1024)
24
25
/*
26
** {======================================================
27
** Error-recovery functions
28
** =======================================================
29
*/
30
31
#if LUA_USE_LONGJMP
32
struct lua_jmpbuf
33
{
34
lua_jmpbuf* volatile prev;
35
volatile int status;
36
jmp_buf buf;
37
};
38
39
// use POSIX versions of setjmp/longjmp if possible: they don't save/restore signal mask and are therefore faster
40
#if defined(__linux__) || defined(__APPLE__)
41
#define LUAU_SETJMP(buf) _setjmp(buf)
42
#define LUAU_LONGJMP(buf, code) _longjmp(buf, code)
43
#else
44
#define LUAU_SETJMP(buf) setjmp(buf)
45
#define LUAU_LONGJMP(buf, code) longjmp(buf, code)
46
#endif
47
48
int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud)
49
{
50
lua_jmpbuf jb;
51
jb.prev = L->global->errorjmp;
52
jb.status = 0;
53
L->global->errorjmp = &jb;
54
55
if (LUAU_SETJMP(jb.buf) == 0)
56
f(L, ud);
57
58
L->global->errorjmp = jb.prev;
59
return jb.status;
60
}
61
62
l_noret luaD_throw(lua_State* L, int errcode)
63
{
64
if (lua_jmpbuf* jb = L->global->errorjmp)
65
{
66
jb->status = errcode;
67
LUAU_LONGJMP(jb->buf, 1);
68
}
69
70
if (L->global->cb.panic)
71
L->global->cb.panic(L, errcode);
72
73
abort();
74
}
75
#else
76
class lua_exception : public std::exception
77
{
78
public:
79
lua_exception(lua_State* L, int status)
80
: L(L)
81
, status(status)
82
{
83
}
84
85
const char* what() const throw() override
86
{
87
// LUA_ERRRUN passes error object on the stack
88
if (status == LUA_ERRRUN)
89
if (const char* str = lua_tostring(L, -1))
90
return str;
91
92
switch (status)
93
{
94
case LUA_ERRRUN:
95
return "lua_exception: runtime error";
96
case LUA_ERRSYNTAX:
97
return "lua_exception: syntax error";
98
case LUA_ERRMEM:
99
return "lua_exception: " LUA_MEMERRMSG;
100
case LUA_ERRERR:
101
return "lua_exception: " LUA_ERRERRMSG;
102
default:
103
return "lua_exception: unexpected exception status";
104
}
105
}
106
107
int getStatus() const
108
{
109
return status;
110
}
111
112
const lua_State* getThread() const
113
{
114
return L;
115
}
116
117
private:
118
lua_State* L;
119
int status;
120
};
121
122
int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud)
123
{
124
int status = 0;
125
126
try
127
{
128
f(L, ud);
129
return 0;
130
}
131
catch (lua_exception& e)
132
{
133
// It is assumed/required that the exception caught here was thrown from the same Luau state.
134
// If this assert fires, it indicates a lua_exception was not properly caught and propagated
135
// to the exception handler for a different Luau state. Report this issue to the Luau team if
136
// you need more information or assistance resolving this assert.
137
LUAU_ASSERT(e.getThread() == L);
138
139
status = e.getStatus();
140
}
141
catch (std::exception& e)
142
{
143
// Luau will never throw this, but this can catch exceptions that escape from C++ implementations of external functions
144
try
145
{
146
// there's no exception object on stack; let's push the error on stack so that error handling below can proceed
147
luaG_pusherror(L, e.what());
148
status = LUA_ERRRUN;
149
}
150
catch (std::exception&)
151
{
152
// out of memory while allocating error string
153
status = LUA_ERRMEM;
154
}
155
}
156
157
return status;
158
}
159
160
l_noret luaD_throw(lua_State* L, int errcode)
161
{
162
throw lua_exception(L, errcode);
163
}
164
#endif
165
166
// }======================================================
167
168
static void correctstack(lua_State* L, TValue* oldstack)
169
{
170
L->top = (L->top - oldstack) + L->stack;
171
for (UpVal* up = L->openupval; up != NULL; up = up->u.open.threadnext)
172
up->v = (up->v - oldstack) + L->stack;
173
for (CallInfo* ci = L->base_ci; ci <= L->ci; ci++)
174
{
175
ci->top = (ci->top - oldstack) + L->stack;
176
ci->base = (ci->base - oldstack) + L->stack;
177
ci->func = (ci->func - oldstack) + L->stack;
178
}
179
L->base = (L->base - oldstack) + L->stack;
180
}
181
182
void luaD_reallocstack(lua_State* L, int newsize, int fornewci)
183
{
184
// throw 'out of memory' error because space for a custom error message cannot be guaranteed here
185
if (newsize > MAX_STACK_SIZE)
186
{
187
// reallocation was performed to setup a new CallInfo frame, which we have to remove
188
if (fornewci)
189
{
190
CallInfo* cip = L->ci - 1;
191
192
L->ci = cip;
193
L->base = cip->base;
194
L->top = cip->top;
195
}
196
197
luaD_throw(L, LUA_ERRMEM);
198
}
199
200
TValue* oldstack = L->stack;
201
int realsize = newsize + EXTRA_STACK;
202
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
203
luaM_reallocarray(L, L->stack, L->stacksize, realsize, TValue, L->memcat);
204
TValue* newstack = L->stack;
205
for (int i = L->stacksize; i < realsize; i++)
206
setnilvalue(newstack + i); // erase new segment
207
L->stacksize = realsize;
208
L->stack_last = newstack + newsize;
209
correctstack(L, oldstack);
210
}
211
212
void luaD_reallocCI(lua_State* L, int newsize)
213
{
214
CallInfo* oldci = L->base_ci;
215
luaM_reallocarray(L, L->base_ci, L->size_ci, newsize, CallInfo, L->memcat);
216
L->size_ci = newsize;
217
L->ci = (L->ci - oldci) + L->base_ci;
218
L->end_ci = L->base_ci + L->size_ci - 1;
219
}
220
221
void luaD_growstack(lua_State* L, int n)
222
{
223
luaD_reallocstack(L, getgrownstacksize(L, n), 0);
224
}
225
226
CallInfo* luaD_growCI(lua_State* L)
227
{
228
// allow extra stack space to handle stack overflow in xpcall
229
const int hardlimit = LUAI_MAXCALLS + (LUAI_MAXCALLS >> 3);
230
231
if (L->size_ci >= hardlimit)
232
luaD_throw(L, LUA_ERRERR); // error while handling stack error
233
234
int request = L->size_ci * 2;
235
luaD_reallocCI(L, L->size_ci >= LUAI_MAXCALLS ? hardlimit : request < LUAI_MAXCALLS ? request : LUAI_MAXCALLS);
236
237
if (L->size_ci > LUAI_MAXCALLS)
238
luaG_runerror(L, "stack overflow");
239
240
return ++L->ci;
241
}
242
243
void luaD_checkCstack(lua_State* L)
244
{
245
// allow extra stack space to handle stack overflow in xpcall
246
const int hardlimit = LUAI_MAXCCALLS + (LUAI_MAXCCALLS >> 3);
247
248
if (L->nCcalls == LUAI_MAXCCALLS)
249
luaG_runerror(L, "C stack overflow");
250
else if (L->nCcalls >= hardlimit)
251
luaD_throw(L, LUA_ERRERR); // error while handling stack error
252
}
253
254
static void performcall(lua_State* L, StkId func, int nresults, bool preparereentry)
255
{
256
if (luau_precall(L, func, nresults) == PCRLUA)
257
{ // is a Lua function?
258
L->ci->flags |= LUA_CALLINFO_RETURN; // luau_execute will stop after returning from the stack frame
259
260
bool oldactive = L->isactive;
261
L->isactive = true;
262
luaC_threadbarrier(L);
263
264
if (FFlag::LuauStacklessPcall)
265
{
266
if (preparereentry)
267
L->status = SCHEDULED_REENTRY;
268
else
269
luau_execute(L);
270
}
271
else
272
{
273
luau_execute(L); // call it
274
}
275
276
if (!oldactive)
277
L->isactive = false;
278
}
279
}
280
281
/*
282
** Call a function (C or Lua). The function to be called is at *func.
283
** The arguments are on the stack, right after the function.
284
** When returns, all the results are on the stack, starting at the original
285
** function position.
286
*/
287
void luaD_callint(lua_State* L, StkId func, int nresults, bool preparereentry)
288
{
289
if (++L->nCcalls >= LUAI_MAXCCALLS)
290
luaD_checkCstack(L);
291
292
// when called from a yieldable C function, maintain yieldable invariant (baseCcalls <= nCcalls)
293
bool fromyieldableccall = false;
294
295
if (L->ci != L->base_ci)
296
{
297
Closure* ccl = clvalue(L->ci->func);
298
299
if (ccl->isC && ccl->c.cont)
300
{
301
fromyieldableccall = true;
302
L->baseCcalls++;
303
}
304
}
305
306
ptrdiff_t funcoffset = savestack(L, func);
307
ptrdiff_t cioffset = saveci(L, L->ci);
308
309
performcall(L, func, nresults, preparereentry);
310
311
bool yielded = FFlag::LuauStacklessPcall ? isyielded(L) : L->status == LUA_YIELD || L->status == LUA_BREAK;
312
313
if (fromyieldableccall)
314
{
315
// restore original yieldable invariant
316
// in case of an error, this would either be restored by luaD_pcall or the thread would no longer be resumable
317
L->baseCcalls--;
318
319
// on yield, we have to set the CallInfo top of the C function including slots for expected results, to restore later
320
if (yielded)
321
{
322
CallInfo* callerci = restoreci(L, cioffset);
323
callerci->top = restorestack(L, funcoffset) + (nresults != LUA_MULTRET ? nresults : 0);
324
}
325
}
326
327
if (nresults != LUA_MULTRET && !yielded)
328
L->top = restorestack(L, funcoffset) + nresults;
329
330
L->nCcalls--;
331
luaC_checkGC(L);
332
}
333
334
void luaD_call(lua_State* L, StkId func, int nresults)
335
{
336
luaD_callint(L, func, nresults, /* preparereentry */ false);
337
}
338
339
// Non-yieldable version of luaD_call, used primarily to call an error handler which cannot yield
340
void luaD_callny(lua_State* L, StkId func, int nresults)
341
{
342
if (++L->nCcalls >= LUAI_MAXCCALLS)
343
luaD_checkCstack(L);
344
345
LUAU_ASSERT(L->nCcalls > L->baseCcalls);
346
347
ptrdiff_t funcoffset = savestack(L, func);
348
349
performcall(L, func, nresults, /* preparereentry */ false);
350
351
if (FFlag::LuauStacklessPcall)
352
LUAU_ASSERT(!isyielded(L));
353
else
354
LUAU_ASSERT(L->status != LUA_YIELD && L->status != LUA_BREAK);
355
356
if (nresults != LUA_MULTRET)
357
L->top = restorestack(L, funcoffset) + nresults;
358
359
L->nCcalls--;
360
luaC_checkGC(L);
361
}
362
363
void luaD_seterrorobj(lua_State* L, int errcode, StkId oldtop)
364
{
365
switch (errcode)
366
{
367
case LUA_ERRMEM:
368
{
369
setsvalue(L, oldtop, luaS_newliteral(L, LUA_MEMERRMSG)); // can not fail because string is pinned in luaopen
370
break;
371
}
372
case LUA_ERRERR:
373
{
374
setsvalue(L, oldtop, luaS_newliteral(L, LUA_ERRERRMSG)); // can not fail because string is pinned in luaopen
375
break;
376
}
377
case LUA_ERRSYNTAX:
378
case LUA_ERRRUN:
379
{
380
setobj2s(L, oldtop, L->top - 1); // error message on current top
381
break;
382
}
383
}
384
L->top = oldtop + 1;
385
}
386
387
static void resume_continue(lua_State* L)
388
{
389
// unroll Luau/C combined stack, processing continuations
390
while ((FFlag::LuauStacklessPcall ? L->status == LUA_OK || L->status == SCHEDULED_REENTRY : L->status == LUA_OK) && L->ci > L->base_ci)
391
{
392
LUAU_ASSERT(L->baseCcalls == L->nCcalls);
393
394
if (FFlag::LuauStacklessPcall)
395
L->status = LUA_OK;
396
397
Closure* cl = curr_func(L);
398
399
if (cl->isC)
400
{
401
LUAU_ASSERT(cl->c.cont);
402
403
// C continuation; we expect this to be followed by Lua continuations
404
int n = cl->c.cont(L, 0);
405
406
// continuation can break or yield again
407
if (L->status == LUA_BREAK || L->status == LUA_YIELD)
408
break;
409
410
luau_poscall(L, L->top - n);
411
}
412
else
413
{
414
// Luau continuation; it terminates at the end of the stack or at another C continuation
415
luau_execute(L);
416
}
417
}
418
}
419
420
static void resume(lua_State* L, void* ud)
421
{
422
StkId firstArg = cast_to(StkId, ud);
423
424
if (FFlag::LuauStacklessPcall)
425
{
426
if (L->status == LUA_OK)
427
{
428
// start coroutine
429
LUAU_ASSERT(L->ci == L->base_ci && firstArg >= L->base);
430
if (firstArg == L->base)
431
luaG_runerror(L, "cannot resume dead coroutine");
432
433
int precallresult = luau_precall(L, firstArg - 1, LUA_MULTRET);
434
435
// on scheduled reentry, we will continue into the yield-continue block below
436
if (L->status == SCHEDULED_REENTRY)
437
{
438
firstArg = L->base;
439
}
440
else
441
{
442
// C function is either completed or yielded, exit
443
if (precallresult != PCRLUA)
444
return;
445
446
// mark to not return past the current Luau function frame
447
L->ci->flags |= LUA_CALLINFO_RETURN;
448
}
449
}
450
451
// restore from yield or reentry
452
if (L->status != LUA_OK)
453
{
454
// resume from previous yield or break
455
LUAU_ASSERT(firstArg >= L->base);
456
LUAU_ASSERT(isyielded(L));
457
L->status = LUA_OK;
458
459
Closure* cl = curr_func(L);
460
461
if (cl->isC)
462
{
463
// if the top stack frame is a C call continuation, resume_continue will handle that case
464
if (!cl->c.cont)
465
{
466
// finish interrupted execution of `OP_CALL'
467
luau_poscall(L, firstArg);
468
}
469
else
470
{
471
// restore arguments we have protected for C continuation
472
L->base = L->ci->base;
473
}
474
}
475
else
476
{
477
// yielded inside a hook: just continue its execution
478
L->base = L->ci->base;
479
}
480
}
481
}
482
else
483
{
484
if (L->status == 0)
485
{
486
// start coroutine
487
LUAU_ASSERT(L->ci == L->base_ci && firstArg >= L->base);
488
if (firstArg == L->base)
489
luaG_runerror(L, "cannot resume dead coroutine");
490
491
if (luau_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
492
return;
493
494
L->ci->flags |= LUA_CALLINFO_RETURN;
495
}
496
else
497
{
498
// resume from previous yield or break
499
LUAU_ASSERT(firstArg >= L->base);
500
LUAU_ASSERT(L->status == LUA_YIELD || L->status == LUA_BREAK);
501
L->status = 0;
502
503
Closure* cl = curr_func(L);
504
505
if (cl->isC)
506
{
507
// if the top stack frame is a C call continuation, resume_continue will handle that case
508
if (!cl->c.cont)
509
{
510
// finish interrupted execution of `OP_CALL'
511
luau_poscall(L, firstArg);
512
}
513
else
514
{
515
// restore arguments we have protected for C continuation
516
L->base = L->ci->base;
517
}
518
}
519
else
520
{
521
// yielded inside a hook: just continue its execution
522
L->base = L->ci->base;
523
}
524
}
525
}
526
527
// run continuations from the stack; typically resumes Luau code and pcalls
528
resume_continue(L);
529
}
530
531
static CallInfo* resume_findhandler(lua_State* L)
532
{
533
CallInfo* ci = L->ci;
534
535
while (ci > L->base_ci)
536
{
537
if (ci->flags & LUA_CALLINFO_HANDLE)
538
return ci;
539
540
ci--;
541
}
542
543
return NULL;
544
}
545
546
static void restore_stack_limit(lua_State* L)
547
{
548
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
549
if (L->size_ci > LUAI_MAXCALLS)
550
{ // there was an overflow?
551
int inuse = cast_int(L->ci - L->base_ci);
552
if (inuse + 1 < LUAI_MAXCALLS) // can `undo' overflow?
553
luaD_reallocCI(L, LUAI_MAXCALLS);
554
}
555
}
556
557
static void resume_handle(lua_State* L, void* ud)
558
{
559
CallInfo* ci = (CallInfo*)ud;
560
Closure* cl = ci_func(ci);
561
562
LUAU_ASSERT(ci->flags & LUA_CALLINFO_HANDLE);
563
LUAU_ASSERT(cl->isC && cl->c.cont);
564
LUAU_ASSERT(L->status != 0);
565
566
// restore nCcalls back to base since this might not have happened during error handling
567
L->nCcalls = L->baseCcalls;
568
569
// make sure we don't run the handler the second time
570
ci->flags &= ~LUA_CALLINFO_HANDLE;
571
572
// restore thread status to LUA_OK since we're handling the error
573
int status = L->status;
574
575
L->status = LUA_OK;
576
577
// push error object to stack top if it's not already there
578
if (status != LUA_ERRRUN)
579
luaD_seterrorobj(L, status, L->top);
580
581
// adjust the stack frame for ci to prepare for cont call
582
L->base = ci->base;
583
ci->top = L->top;
584
585
// save ci pointer - it will be invalidated by cont call!
586
ptrdiff_t old_ci = saveci(L, ci);
587
588
// handle the error in continuation; note that this executes on top of original stack!
589
int n = cl->c.cont(L, status);
590
591
// restore the stack frame to the frame with continuation
592
L->ci = restoreci(L, old_ci);
593
594
// close eventual pending closures; this means it's now safe to restore stack
595
luaF_close(L, L->ci->base);
596
597
restore_stack_limit(L);
598
599
// finish cont call and restore stack to previous ci top
600
luau_poscall(L, L->top - n);
601
602
// run remaining continuations from the stack; typically resumes pcalls
603
resume_continue(L);
604
}
605
606
static int resume_error(lua_State* L, const char* msg, int narg)
607
{
608
L->top -= narg;
609
setsvalue(L, L->top, luaS_new(L, msg));
610
incr_top(L);
611
return LUA_ERRRUN;
612
}
613
614
static int resume_start(lua_State* L, lua_State* from, int nargs)
615
{
616
api_check(L, L->top - L->base >= nargs);
617
618
if (L->status != LUA_YIELD && L->status != LUA_BREAK && (L->status != 0 || L->ci != L->base_ci))
619
return resume_error(L, "cannot resume non-suspended coroutine", nargs);
620
621
L->nCcalls = from ? from->nCcalls : 0;
622
if (L->nCcalls >= LUAI_MAXCCALLS)
623
return resume_error(L, "C stack overflow", nargs);
624
625
L->baseCcalls = ++L->nCcalls;
626
L->isactive = true;
627
628
luaC_threadbarrier(L);
629
630
return LUA_OK;
631
}
632
633
static int resume_finish(lua_State* L, int status)
634
{
635
CallInfo* ch = NULL;
636
while (status != LUA_OK && (ch = resume_findhandler(L)) != NULL)
637
{
638
if (FFlag::LuauStacklessPcall && lua_isyieldable(L) != 0 && L->global->cb.debugprotectederror)
639
{
640
L->global->cb.debugprotectederror(L);
641
642
// debug hook is only allowed to break
643
if (L->status == LUA_BREAK)
644
{
645
status = LUA_OK;
646
break;
647
}
648
}
649
650
L->status = cast_byte(status);
651
status = luaD_rawrunprotected(L, resume_handle, ch);
652
}
653
654
// C call count base was set to an incremented value of C call count in resume, so we decrement here
655
L->nCcalls = --L->baseCcalls;
656
657
// make execution context non-yieldable as we are leaving the resume
658
L->baseCcalls = L->nCcalls;
659
660
L->isactive = false;
661
662
if (status != LUA_OK)
663
{
664
L->status = cast_byte(status);
665
luaD_seterrorobj(L, status, L->top);
666
L->ci->top = L->top;
667
}
668
else if (L->status == LUA_OK)
669
{
670
expandstacklimit(L, L->top);
671
}
672
673
return L->status;
674
}
675
676
int lua_resume(lua_State* L, lua_State* from, int nargs)
677
{
678
if (int starterror = resume_start(L, from, nargs))
679
return starterror;
680
681
int status = luaD_rawrunprotected(L, resume, L->top - nargs);
682
683
return resume_finish(L, status);
684
}
685
686
int lua_resumeerror(lua_State* L, lua_State* from)
687
{
688
if (int starterror = resume_start(L, from, 1))
689
return starterror;
690
691
int status = LUA_ERRRUN;
692
693
if (CallInfo* ci = resume_findhandler(L))
694
{
695
L->status = cast_byte(status);
696
status = luaD_rawrunprotected(L, resume_handle, ci);
697
}
698
699
return resume_finish(L, status);
700
}
701
702
int lua_yield(lua_State* L, int nresults)
703
{
704
if (L->nCcalls > L->baseCcalls)
705
luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
706
L->base = L->top - nresults; // protect stack slots below
707
L->status = LUA_YIELD;
708
return -1;
709
}
710
711
int lua_break(lua_State* L)
712
{
713
if (L->nCcalls > L->baseCcalls)
714
luaG_runerror(L, "attempt to break across metamethod/C-call boundary");
715
L->status = LUA_BREAK;
716
return -1;
717
}
718
719
int lua_isyieldable(lua_State* L)
720
{
721
return (L->nCcalls <= L->baseCcalls);
722
}
723
724
static void callerrfunc(lua_State* L, void* ud)
725
{
726
StkId errfunc = cast_to(StkId, ud);
727
728
setobj2s(L, L->top, L->top - 1);
729
setobj2s(L, L->top - 1, errfunc);
730
incr_top(L);
731
732
luaD_callny(L, L->top - 2, 1);
733
}
734
735
int luaD_pcall(lua_State* L, Pfunc func, void* u, ptrdiff_t old_top, ptrdiff_t ef)
736
{
737
unsigned short oldnCcalls = L->nCcalls;
738
unsigned short oldbaseCcalls = L->baseCcalls;
739
ptrdiff_t old_ci = saveci(L, L->ci);
740
bool oldactive = L->isactive;
741
int status = luaD_rawrunprotected(L, func, u);
742
if (status != 0)
743
{
744
int errstatus = status;
745
746
// call user-defined error function (used in xpcall)
747
if (ef)
748
{
749
// push error object to stack top if it's not already there
750
if (status != LUA_ERRRUN)
751
luaD_seterrorobj(L, status, L->top);
752
753
// if errfunc fails, we fail with "error in error handling" or "not enough memory"
754
int err = luaD_rawrunprotected(L, callerrfunc, restorestack(L, ef));
755
756
// in general we preserve the status, except for cases when the error handler fails
757
// out of memory is treated specially because it's common for it to be cascading, in which case we preserve the code
758
if (err == 0)
759
errstatus = LUA_ERRRUN;
760
else if (status == LUA_ERRMEM && err == LUA_ERRMEM)
761
errstatus = LUA_ERRMEM;
762
else
763
errstatus = status = LUA_ERRERR;
764
}
765
766
// since the call failed with an error, we might have to reset the 'active' thread state
767
if (!oldactive)
768
L->isactive = false;
769
770
bool yieldable = L->nCcalls <= L->baseCcalls; // Inlined logic from 'lua_isyieldable' to avoid potential for an out of line call.
771
772
// restore nCcalls and baseCcalls before calling the debugprotectederror callback which may rely on the proper value to have been restored.
773
L->nCcalls = oldnCcalls;
774
L->baseCcalls = oldbaseCcalls;
775
776
// an error occurred, check if we have a protected error callback
777
if (yieldable && L->global->cb.debugprotectederror)
778
{
779
L->global->cb.debugprotectederror(L);
780
781
// debug hook is only allowed to break
782
if (L->status == LUA_BREAK)
783
return 0;
784
}
785
786
StkId oldtop = restorestack(L, old_top);
787
luaF_close(L, oldtop); // close eventual pending closures
788
luaD_seterrorobj(L, errstatus, oldtop);
789
L->ci = restoreci(L, old_ci);
790
L->base = L->ci->base;
791
restore_stack_limit(L);
792
}
793
return status;
794
}
795
796