diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-11 16:11:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-11 16:11:50 -0300 |
commit | 96f9643f330a4bf0f8cd1973fecdd7161ffbbf68 (patch) | |
tree | 78b08f9963feab6863673e42ab98fbc5dad4c792 | |
parent | 84058b15068a382e66f4eeb4e29a2dbf1704fa8b (diff) | |
download | lua-96f9643f330a4bf0f8cd1973fecdd7161ffbbf68.tar.gz lua-96f9643f330a4bf0f8cd1973fecdd7161ffbbf68.tar.bz2 lua-96f9643f330a4bf0f8cd1973fecdd7161ffbbf68.zip |
Bug: wrong 'nCcalls' when resuming a coroutine
The counter 'nCcalls' now includes the number of CallInfo structures
pre-allocated (so that these "potential" C calls can be made without
checking 'nCcalls'). So, when copying this value from a thread to
another, in 'lua_resume', it must be corrected to the number of
CallInfo structures in the thread being resumed.
-rw-r--r-- | ldo.c | 9 | ||||
-rw-r--r-- | lstate.h | 20 |
2 files changed, 24 insertions, 5 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.201 2018/05/22 12:02:36 roberto Exp roberto $ | 2 | ** $Id: ldo.c $ |
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 | */ |
@@ -137,6 +137,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
137 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | 137 | int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { |
138 | unsigned short oldnCcalls = L->nCcalls - L->nci; | 138 | unsigned short oldnCcalls = L->nCcalls - L->nci; |
139 | struct lua_longjmp lj; | 139 | struct lua_longjmp lj; |
140 | lua_assert(L->nCcalls >= L->nci); | ||
140 | lj.status = LUA_OK; | 141 | lj.status = LUA_OK; |
141 | lj.previous = L->errorJmp; /* chain new error handler */ | 142 | lj.previous = L->errorJmp; /* chain new error handler */ |
142 | L->errorJmp = &lj; | 143 | L->errorJmp = &lj; |
@@ -653,7 +654,10 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
653 | } | 654 | } |
654 | else if (L->status != LUA_YIELD) | 655 | else if (L->status != LUA_YIELD) |
655 | return resume_error(L, "cannot resume dead coroutine", nargs); | 656 | return resume_error(L, "cannot resume dead coroutine", nargs); |
656 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; | 657 | if (from == NULL) |
658 | L->nCcalls = 1; | ||
659 | else /* correct 'nCcalls' for this thread */ | ||
660 | L->nCcalls = from->nCcalls - from->nci + L->nci + 1; | ||
657 | if (L->nCcalls >= LUAI_MAXCCALLS) | 661 | if (L->nCcalls >= LUAI_MAXCCALLS) |
658 | return resume_error(L, "C stack overflow", nargs); | 662 | return resume_error(L, "C stack overflow", nargs); |
659 | luai_userstateresume(L, nargs); | 663 | luai_userstateresume(L, nargs); |
@@ -677,7 +681,6 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
677 | *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield | 681 | *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield |
678 | : cast_int(L->top - (L->ci->func + 1)); | 682 | : cast_int(L->top - (L->ci->func + 1)); |
679 | L->nny = oldnny; /* restore 'nny' */ | 683 | L->nny = oldnny; /* restore 'nny' */ |
680 | L->nCcalls--; | ||
681 | lua_unlock(L); | 684 | lua_unlock(L); |
682 | return status; | 685 | return status; |
683 | } | 686 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.159 2018/06/15 19:31:22 roberto Exp roberto $ | 2 | ** $Id: lstate.h $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -49,6 +49,22 @@ | |||
49 | */ | 49 | */ |
50 | 50 | ||
51 | 51 | ||
52 | /* | ||
53 | |||
54 | ** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of | ||
55 | ** how many "C calls" it has in the C stack, to avoid C-stack overflow. | ||
56 | ** This count is very rough approximation; it considers only recursive | ||
57 | ** functions inside the interpreter, as non-recursive calls can be | ||
58 | ** considered using a fixed (although unknown) amount of stack space. | ||
59 | ** | ||
60 | ** The proper count also includes the number of CallInfo structures | ||
61 | ** allocated by Lua, as a kind of "potential" calls. So, when Lua | ||
62 | ** calls a function (and "consumes" one CallInfo), it needs neither to | ||
63 | ** increment nor to check 'nCcalls', as its use of C stack is already | ||
64 | ** accounted for. | ||
65 | |||
66 | */ | ||
67 | |||
52 | struct lua_longjmp; /* defined in ldo.c */ | 68 | struct lua_longjmp; /* defined in ldo.c */ |
53 | 69 | ||
54 | 70 | ||
@@ -212,7 +228,7 @@ struct lua_State { | |||
212 | int basehookcount; | 228 | int basehookcount; |
213 | int hookcount; | 229 | int hookcount; |
214 | unsigned short nny; /* number of non-yieldable calls in stack */ | 230 | unsigned short nny; /* number of non-yieldable calls in stack */ |
215 | unsigned short nCcalls; /* number of nested C calls */ | 231 | unsigned short nCcalls; /* number of nested C calls + 'nny' */ |
216 | l_signalT hookmask; | 232 | l_signalT hookmask; |
217 | lu_byte allowhook; | 233 | lu_byte allowhook; |
218 | }; | 234 | }; |