aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c127
1 files changed, 67 insertions, 60 deletions
diff --git a/ldo.c b/ldo.c
index aa159cf0..45cfd592 100644
--- a/ldo.c
+++ b/ldo.c
@@ -565,25 +565,64 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
565 565
566 566
567/* 567/*
568** Completes the execution of an interrupted C function, calling its 568** Finish the job of 'lua_pcallk' after it was interrupted by an yield.
569** continuation function. 569** (The caller, 'finishCcall', does the final call to 'adjustresults'.)
570** The main job is to complete the 'luaD_pcall' called by 'lua_pcallk'.
571** If a '__close' method yields here, eventually control will be back
572** to 'finishCcall' (when that '__close' method finally returns) and
573** 'finishpcallk' will run again and close any still pending '__close'
574** methods. Similarly, if a '__close' method errs, 'precover' calls
575** 'unroll' which calls ''finishCcall' and we are back here again, to
576** close any pending '__close' methods.
577** Note that, up to the call to 'luaF_close', the corresponding
578** 'CallInfo' is not modified, so that this repeated run works like the
579** first one (except that it has at least one less '__close' to do). In
580** particular, field CIST_RECST preserves the error status across these
581** multiple runs, changing only if there is a new error.
570*/ 582*/
571static void finishCcall (lua_State *L, int status) { 583static int finishpcallk (lua_State *L, CallInfo *ci) {
572 CallInfo *ci = L->ci; 584 int status = getcistrecst(ci); /* get original status */
585 if (status == LUA_OK) /* no error? */
586 status = LUA_YIELD; /* was interrupted by an yield */
587 else { /* error */
588 StkId func = restorestack(L, ci->u2.funcidx);
589 L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */
590 luaF_close(L, func, status, 1); /* can yield or raise an error */
591 func = restorestack(L, ci->u2.funcidx); /* stack may be moved */
592 luaD_seterrorobj(L, status, func);
593 luaD_shrinkstack(L); /* restore stack size in case of overflow */
594 setcistrecst(ci, LUA_OK); /* clear original status */
595 }
596 ci->callstatus &= ~CIST_YPCALL;
597 L->errfunc = ci->u.c.old_errfunc;
598 /* if it is here, there were errors or yields; unlike 'lua_pcallk',
599 do not change status */
600 return status;
601}
602
603
604/*
605** Completes the execution of a C function interrupted by an yield.
606** The interruption must have happened while the function was
607** executing 'lua_callk' or 'lua_pcallk'. In the second case, the
608** call to 'finishpcallk' finishes the interrupted execution of
609** 'lua_pcallk'. After that, it calls the continuation of the
610** interrupted function and finally it completes the job of the
611** 'luaD_call' that called the function.
612** In the call to 'adjustresults', we do not know the number of
613** results of the function called by 'lua_callk'/'lua_pcallk',
614** so we are conservative and use LUA_MULTRET (always adjust).
615*/
616static void finishCcall (lua_State *L, CallInfo *ci) {
573 int n; 617 int n;
618 int status = LUA_YIELD; /* default if there were no errors */
574 /* must have a continuation and must be able to call it */ 619 /* must have a continuation and must be able to call it */
575 lua_assert(ci->u.c.k != NULL && yieldable(L)); 620 lua_assert(ci->u.c.k != NULL && yieldable(L));
576 /* error status can only happen in a protected call */ 621 if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */
577 lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); 622 status = finishpcallk(L, ci); /* finish it */
578 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ 623 adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */
579 ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */
580 L->errfunc = ci->u.c.old_errfunc; /* with the same error function */
581 }
582 /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already
583 handled */
584 adjustresults(L, ci->nresults);
585 lua_unlock(L); 624 lua_unlock(L);
586 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ 625 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */
587 lua_lock(L); 626 lua_lock(L);
588 api_checknelems(L, n); 627 api_checknelems(L, n);
589 luaD_poscall(L, ci, n); /* finish 'luaD_call' */ 628 luaD_poscall(L, ci, n); /* finish 'luaD_call' */
@@ -600,7 +639,7 @@ static void unroll (lua_State *L, void *ud) {
600 UNUSED(ud); 639 UNUSED(ud);
601 while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ 640 while ((ci = L->ci) != &L->base_ci) { /* something in the stack */
602 if (!isLua(ci)) /* C function? */ 641 if (!isLua(ci)) /* C function? */
603 finishCcall(L, LUA_YIELD); /* complete its execution */ 642 finishCcall(L, ci); /* complete its execution */
604 else { /* Lua function */ 643 else { /* Lua function */
605 luaV_finishOp(L); /* finish interrupted instruction */ 644 luaV_finishOp(L); /* finish interrupted instruction */
606 luaV_execute(L, ci); /* execute down to higher C 'boundary' */ 645 luaV_execute(L, ci); /* execute down to higher C 'boundary' */
@@ -624,40 +663,6 @@ static CallInfo *findpcall (lua_State *L) {
624 663
625 664
626/* 665/*
627** Auxiliary structure to call 'recover' in protected mode.
628*/
629struct RecoverS {
630 int status;
631 CallInfo *ci;
632};
633
634
635/*
636** Recovers from an error in a coroutine: completes the execution of the
637** interrupted 'luaD_pcall', completes the interrupted C function which
638** called 'lua_pcallk', and continues running the coroutine. If there is
639** an error in 'luaF_close', this function will be called again and the
640** coroutine will continue from where it left.
641*/
642static void recover (lua_State *L, void *ud) {
643 struct RecoverS *r = cast(struct RecoverS *, ud);
644 int status = r->status;
645 CallInfo *ci = r->ci; /* recover point */
646 StkId func = restorestack(L, ci->u2.funcidx);
647 /* "finish" luaD_pcall */
648 L->ci = ci;
649 L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
650 luaF_close(L, func, status, 0); /* may change the stack */
651 func = restorestack(L, ci->u2.funcidx);
652 luaD_seterrorobj(L, status, func);
653 luaD_shrinkstack(L); /* restore stack size in case of overflow */
654 L->errfunc = ci->u.c.old_errfunc;
655 finishCcall(L, status); /* finish 'lua_pcallk' callee */
656 unroll(L, NULL); /* continue running the coroutine */
657}
658
659
660/*
661** Signal an error in the call to 'lua_resume', not in the execution 666** Signal an error in the call to 'lua_resume', not in the execution
662** of the coroutine itself. (Such errors should not be handled by any 667** of the coroutine itself. (Such errors should not be handled by any
663** coroutine error handler and should not kill the coroutine.) 668** coroutine error handler and should not kill the coroutine.)
@@ -705,19 +710,21 @@ static void resume (lua_State *L, void *ud) {
705 710
706 711
707/* 712/*
708** Calls 'recover' in protected mode, repeating while there are 713** Unrolls a coroutine in protected mode while there are recoverable
709** recoverable errors, that is, errors inside a protected call. (Any 714** errors, that is, errors inside a protected call. (Any error
710** error interrupts 'recover', and this loop protects it again so it 715** interrupts 'unroll', and this loop protects it again so it can
711** can continue.) Stops with a normal end (status == LUA_OK), an yield 716** continue.) Stops with a normal end (status == LUA_OK), an yield
712** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't 717** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't
713** find a recover point). 718** find a recover point).
714*/ 719*/
715static int p_recover (lua_State *L, int status) { 720static int precover (lua_State *L, int status) {
716 struct RecoverS r; 721 CallInfo *ci;
717 r.status = status; 722 while (errorstatus(status) && (ci = findpcall(L)) != NULL) {
718 while (errorstatus(status) && (r.ci = findpcall(L)) != NULL) 723 L->ci = ci; /* go down to recovery functions */
719 r.status = luaD_rawrunprotected(L, recover, &r); 724 setcistrecst(ci, status); /* status to finish 'pcall' */
720 return r.status; 725 status = luaD_rawrunprotected(L, unroll, NULL);
726 }
727 return status;
721} 728}
722 729
723 730
@@ -738,7 +745,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
738 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 745 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
739 status = luaD_rawrunprotected(L, resume, &nargs); 746 status = luaD_rawrunprotected(L, resume, &nargs);
740 /* continue running after recoverable errors */ 747 /* continue running after recoverable errors */
741 status = p_recover(L, status); 748 status = precover(L, status);
742 if (likely(!errorstatus(status))) 749 if (likely(!errorstatus(status)))
743 lua_assert(status == L->status); /* normal end or yield */ 750 lua_assert(status == L->status); /* normal end or yield */
744 else { /* unrecoverable error */ 751 else { /* unrecoverable error */