aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-12-08 16:59:24 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-12-08 16:59:24 -0200
commit2643da67c686bac5e29fdf94f54a06e33eb08dd0 (patch)
tree20e934b3096eece9f8f337fd572768327924b05e /ldo.c
parented117bb42afc67c83c677347842b35f1ebd51877 (diff)
downloadlua-2643da67c686bac5e29fdf94f54a06e33eb08dd0.tar.gz
lua-2643da67c686bac5e29fdf94f54a06e33eb08dd0.tar.bz2
lua-2643da67c686bac5e29fdf94f54a06e33eb08dd0.zip
error messages from 'lua_resume' must be generated in protected mode,
to avoid raising memory errors
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/ldo.c b/ldo.c
index ef1e045b..7504f189 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.73 2009/11/25 15:27:51 roberto Exp roberto $ 2** $Id: ldo.c,v 2.74 2009/11/27 15:37:59 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -404,19 +404,38 @@ static void unroll (lua_State *L, void *ud) {
404} 404}
405 405
406 406
407/*
408** data to be passed to 'resume' by 'lua_resume'
409*/
410struct ResumeData {
411 StkId firstArg; /* stack index of first argument */
412 int recover; /* should try to recover in case of errors */
413};
414
415
416/*
417** do the work for 'lua_resume' in protected mode
418*/
407static void resume (lua_State *L, void *ud) { 419static void resume (lua_State *L, void *ud) {
408 StkId firstArg = cast(StkId, ud); 420 struct ResumeData *rd = cast(struct ResumeData *, ud);
409 CallInfo *ci = L->ci; 421 CallInfo *ci = L->ci;
410 if (L->status == LUA_OK) { /* start coroutine? */ 422 if (G(L)->nCcalls >= LUAI_MAXCCALLS)
411 lua_assert(ci == &L->base_ci); 423 luaG_runerror(L, "C stack overflow");
412 if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ 424 if (L->status == LUA_OK) { /* may be starting a coroutine */
425 if (ci != &L->base_ci) { /* not in base level? */
426 rd->recover = 0; /* thread may not be running as a coroutine */
427 luaG_runerror(L, "cannot resume non-suspended coroutine");
428 }
429 /* coroutine is in base level; start running it */
430 if (!luaD_precall(L, rd->firstArg - 1, LUA_MULTRET)) /* Lua function? */
413 luaV_execute(L); /* call it */ 431 luaV_execute(L); /* call it */
414 } 432 }
433 else if (L->status != LUA_YIELD)
434 luaG_runerror(L, "cannot resume dead coroutine");
415 else { /* resuming from previous yield */ 435 else { /* resuming from previous yield */
416 lua_assert(L->status == LUA_YIELD);
417 L->status = LUA_OK; 436 L->status = LUA_OK;
418 if (isLua(ci)) /* yielded inside a hook? */ 437 if (isLua(ci)) /* yielded inside a hook? */
419 luaV_execute(L); 438 luaV_execute(L); /* just continue running Lua code */
420 else { /* 'common' yield */ 439 else { /* 'common' yield */
421 if (ci->u.c.k != NULL) { /* does it have a continuation? */ 440 if (ci->u.c.k != NULL) { /* does it have a continuation? */
422 int n; 441 int n;
@@ -427,25 +446,16 @@ static void resume (lua_State *L, void *ud) {
427 n = (*ci->u.c.k)(L); /* call continuation */ 446 n = (*ci->u.c.k)(L); /* call continuation */
428 lua_lock(L); 447 lua_lock(L);
429 api_checknelems(L, n); 448 api_checknelems(L, n);
430 firstArg = L->top - n; 449 rd->firstArg = L->top - n; /* yield results come from continuation */
431 } 450 }
432 G(L)->nCcalls--; /* finish 'luaD_call' */ 451 G(L)->nCcalls--; /* finish 'luaD_call' */
433 luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ 452 luaD_poscall(L, rd->firstArg); /* finish 'luaD_precall' */
434 } 453 }
435 unroll(L, NULL); 454 unroll(L, NULL);
436 } 455 }
437} 456}
438 457
439 458
440static int resume_error (lua_State *L, const char *msg) {
441 L->top = L->ci->func + 1;
442 setsvalue2s(L, L->top, luaS_new(L, msg));
443 incr_top(L);
444 lua_unlock(L);
445 return LUA_ERRRUN;
446}
447
448
449/* 459/*
450** check whether thread has a suspended protected call 460** check whether thread has a suspended protected call
451*/ 461*/
@@ -479,37 +489,34 @@ static int recover (lua_State *L, int status) {
479 489
480 490
481LUA_API int lua_resume (lua_State *L, int nargs) { 491LUA_API int lua_resume (lua_State *L, int nargs) {
492 struct ResumeData rd;
482 int status; 493 int status;
483 lua_lock(L); 494 lua_lock(L);
484 if (L->status != LUA_YIELD) {
485 if (L->status != LUA_OK)
486 return resume_error(L, "cannot resume dead coroutine");
487 else if (L->ci != &L->base_ci)
488 return resume_error(L, "cannot resume non-suspended coroutine");
489 }
490 luai_userstateresume(L, nargs); 495 luai_userstateresume(L, nargs);
491 if (G(L)->nCcalls >= LUAI_MAXCCALLS)
492 return resume_error(L, "C stack overflow");
493 ++G(L)->nCcalls; /* count resume */ 496 ++G(L)->nCcalls; /* count resume */
494 L->nny = 0; /* allow yields */ 497 L->nny = 0; /* allow yields */
495 status = luaD_rawrunprotected(L, resume, L->top - nargs); 498 rd.firstArg = L->top - nargs; rd.recover = 1;
496 while (status != LUA_OK && status != LUA_YIELD) { /* error? */ 499 status = luaD_rawrunprotected(L, resume, &rd);
497 if (recover(L, status)) /* recover point? */ 500 if (rd.recover) {
498 status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ 501 while (status != LUA_OK && status != LUA_YIELD) { /* error? */
499 else { /* unrecoverable error */ 502 if (recover(L, status)) /* recover point? */
500 L->status = cast_byte(status); /* mark thread as `dead' */ 503 status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */
501 luaD_seterrorobj(L, status, L->top); 504 else { /* unrecoverable error */
502 L->ci->top = L->top; 505 L->status = cast_byte(status); /* mark thread as `dead' */
503 break; 506 luaD_seterrorobj(L, status, L->top);
507 L->ci->top = L->top;
508 break;
509 }
504 } 510 }
511 lua_assert(status == L->status);
505 } 512 }
506 lua_assert(status == L->status);
507 L->nny = 1; /* do not allow yields */ 513 L->nny = 1; /* do not allow yields */
508 --G(L)->nCcalls; 514 --G(L)->nCcalls;
509 lua_unlock(L); 515 lua_unlock(L);
510 return status; 516 return status;
511} 517}
512 518
519
513LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { 520LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) {
514 CallInfo *ci = L->ci; 521 CallInfo *ci = L->ci;
515 luai_userstateyield(L, nresults); 522 luai_userstateyield(L, nresults);