@@ -408,24 +408,27 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
408408 case LUA_MULTRET :
409409 wanted = nres ; /* we want all results */
410410 break ;
411- default : /* multiple results ( or to-be-closed variables) */
411+ default : /* two/more results and/ or to-be-closed variables */
412412 if (hastocloseCfunc (wanted )) { /* to-be-closed variables? */
413413 ptrdiff_t savedres = savestack (L , res );
414- luaF_close ( L , res , CLOSEKTOP , 0 ) ; /* may change the stack */
415- wanted = codeNresults ( wanted ); /* correct value */
416- if ( wanted == LUA_MULTRET )
417- wanted = nres ;
414+ L -> ci -> callstatus |= CIST_CLSRET ; /* in case of yields */
415+ L -> ci -> u2 . nres = nres ;
416+ luaF_close ( L , res , CLOSEKTOP , 1 );
417+ L -> ci -> callstatus &= ~ CIST_CLSRET ;
418418 if (L -> hookmask ) /* if needed, call hook after '__close's */
419419 rethook (L , L -> ci , nres );
420420 res = restorestack (L , savedres ); /* close and hook can move stack */
421+ wanted = decodeNresults (wanted );
422+ if (wanted == LUA_MULTRET )
423+ wanted = nres ; /* we want all results */
421424 }
422425 break ;
423426 }
427+ /* generic case */
424428 firstresult = L -> top - nres ; /* index of first result */
425- /* move all results to correct place */
426- if (nres > wanted )
427- nres = wanted ; /* don't need more than that */
428- for (i = 0 ; i < nres ; i ++ )
429+ if (nres > wanted ) /* extra results? */
430+ nres = wanted ; /* don't need them */
431+ for (i = 0 ; i < nres ; i ++ ) /* move all results to correct place */
429432 setobjs2s (L , res + i , firstresult + i );
430433 for (; i < wanted ; i ++ ) /* complete wanted number of results */
431434 setnilvalue (s2v (res + i ));
@@ -445,6 +448,9 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
445448 rethook (L , ci , nres );
446449 /* move results to proper place */
447450 moveresults (L , ci -> func , nres , wanted );
451+ /* function cannot be in any of these cases when returning */
452+ lua_assert (!(ci -> callstatus &
453+ (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET )));
448454 L -> ci = ci -> previous ; /* back to caller (after closing variables) */
449455}
450456
@@ -615,28 +621,36 @@ static int finishpcallk (lua_State *L, CallInfo *ci) {
615621
616622/*
617623** Completes the execution of a C function interrupted by an yield.
618- ** The interruption must have happened while the function was
619- ** executing 'lua_callk' or 'lua_pcallk'. In the second case, the
620- ** call to 'finishpcallk' finishes the interrupted execution of
621- ** 'lua_pcallk'. After that, it calls the continuation of the
622- ** interrupted function and finally it completes the job of the
623- ** 'luaD_call' that called the function.
624- ** In the call to 'adjustresults', we do not know the number of
625- ** results of the function called by 'lua_callk'/'lua_pcallk',
626- ** so we are conservative and use LUA_MULTRET (always adjust).
624+ ** The interruption must have happened while the function was either
625+ ** closing its tbc variables in 'moveresults' or executing
626+ ** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes
627+ ** 'luaD_poscall'. In the second case, the call to 'finishpcallk'
628+ ** finishes the interrupted execution of 'lua_pcallk'. After that, it
629+ ** calls the continuation of the interrupted function and finally it
630+ ** completes the job of the 'luaD_call' that called the function. In
631+ ** the call to 'adjustresults', we do not know the number of results
632+ ** of the function called by 'lua_callk'/'lua_pcallk', so we are
633+ ** conservative and use LUA_MULTRET (always adjust).
627634*/
628635static void finishCcall (lua_State * L , CallInfo * ci ) {
629- int n ;
630- int status = LUA_YIELD ; /* default if there were no errors */
631- /* must have a continuation and must be able to call it */
632- lua_assert (ci -> u .c .k != NULL && yieldable (L ));
633- if (ci -> callstatus & CIST_YPCALL ) /* was inside a 'lua_pcallk'? */
634- status = finishpcallk (L , ci ); /* finish it */
635- adjustresults (L , LUA_MULTRET ); /* finish 'lua_callk' */
636- lua_unlock (L );
637- n = (* ci -> u .c .k )(L , status , ci -> u .c .ctx ); /* call continuation */
638- lua_lock (L );
639- api_checknelems (L , n );
636+ int n ; /* actual number of results from C function */
637+ if (ci -> callstatus & CIST_CLSRET ) { /* was returning? */
638+ lua_assert (hastocloseCfunc (ci -> nresults ));
639+ n = ci -> u2 .nres ; /* just redo 'luaD_poscall' */
640+ /* don't need to reset CIST_CLSRET, as it will be set again anyway */
641+ }
642+ else {
643+ int status = LUA_YIELD ; /* default if there were no errors */
644+ /* must have a continuation and must be able to call it */
645+ lua_assert (ci -> u .c .k != NULL && yieldable (L ));
646+ if (ci -> callstatus & CIST_YPCALL ) /* was inside a 'lua_pcallk'? */
647+ status = finishpcallk (L , ci ); /* finish it */
648+ adjustresults (L , LUA_MULTRET ); /* finish 'lua_callk' */
649+ lua_unlock (L );
650+ n = (* ci -> u .c .k )(L , status , ci -> u .c .ctx ); /* call continuation */
651+ lua_lock (L );
652+ api_checknelems (L , n );
653+ }
640654 luaD_poscall (L , ci , n ); /* finish 'luaD_call' */
641655}
642656
0 commit comments