diff options
| -rw-r--r-- | ldo.c | 6 | ||||
| -rw-r--r-- | testes/coroutine.lua | 26 |
2 files changed, 25 insertions, 7 deletions
| @@ -641,11 +641,11 @@ static int recover (lua_State *L, int status) { | |||
| 641 | if (ci == NULL) return 0; /* no recovery point */ | 641 | if (ci == NULL) return 0; /* no recovery point */ |
| 642 | /* "finish" luaD_pcall */ | 642 | /* "finish" luaD_pcall */ |
| 643 | oldtop = restorestack(L, ci->u2.funcidx); | 643 | oldtop = restorestack(L, ci->u2.funcidx); |
| 644 | luaF_close(L, oldtop, status); /* may change the stack */ | ||
| 645 | oldtop = restorestack(L, ci->u2.funcidx); | ||
| 646 | luaD_seterrorobj(L, status, oldtop); | ||
| 647 | L->ci = ci; | 644 | L->ci = ci; |
| 648 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 645 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ |
| 646 | status = luaF_close(L, oldtop, status); /* may change the stack */ | ||
| 647 | oldtop = restorestack(L, ci->u2.funcidx); | ||
| 648 | luaD_seterrorobj(L, status, oldtop); | ||
| 649 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ | 649 | luaD_shrinkstack(L); /* restore stack size in case of overflow */ |
| 650 | L->errfunc = ci->u.c.old_errfunc; | 650 | L->errfunc = ci->u.c.old_errfunc; |
| 651 | return 1; /* continue running the coroutine */ | 651 | return 1; /* continue running the coroutine */ |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 955f6776..5b927151 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
| @@ -124,6 +124,11 @@ x, a = nil | |||
| 124 | 124 | ||
| 125 | 125 | ||
| 126 | -- coroutine closing | 126 | -- coroutine closing |
| 127 | |||
| 128 | local function func2close (f) | ||
| 129 | return setmetatable({}, {__close = f}) | ||
| 130 | end | ||
| 131 | |||
| 127 | do | 132 | do |
| 128 | -- ok to close a dead coroutine | 133 | -- ok to close a dead coroutine |
| 129 | local co = coroutine.create(print) | 134 | local co = coroutine.create(print) |
| @@ -146,10 +151,6 @@ do | |||
| 146 | -- to-be-closed variables in coroutines | 151 | -- to-be-closed variables in coroutines |
| 147 | local X | 152 | local X |
| 148 | 153 | ||
| 149 | local function func2close (f) | ||
| 150 | return setmetatable({}, {__close = f}) | ||
| 151 | end | ||
| 152 | |||
| 153 | co = coroutine.create(function () | 154 | co = coroutine.create(function () |
| 154 | local x <close> = func2close(function (self, err) | 155 | local x <close> = func2close(function (self, err) |
| 155 | assert(err == nil); X = false | 156 | assert(err == nil); X = false |
| @@ -192,6 +193,23 @@ do | |||
| 192 | 193 | ||
| 193 | end | 194 | end |
| 194 | 195 | ||
| 196 | do | ||
| 197 | -- <close> versus pcall in coroutines | ||
| 198 | local X = false | ||
| 199 | local Y = false | ||
| 200 | function foo () | ||
| 201 | local x <close> = func2close(function (self, err) | ||
| 202 | Y = debug.getinfo(2) | ||
| 203 | X = err | ||
| 204 | end) | ||
| 205 | error(43) | ||
| 206 | end | ||
| 207 | co = coroutine.create(function () return pcall(foo) end) | ||
| 208 | local st1, st2, err = coroutine.resume(co) | ||
| 209 | assert(st1 and not st2 and err == 43) | ||
| 210 | assert(X == 43 and Y.name == "pcall") | ||
| 211 | end | ||
| 212 | |||
| 195 | 213 | ||
| 196 | -- yielding across C boundaries | 214 | -- yielding across C boundaries |
| 197 | 215 | ||
