diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-06-05 13:16:25 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-06-05 13:16:25 -0300 |
commit | b4d5dff8ec4f1c8a44db66d368e95d359b04aea7 (patch) | |
tree | e87fbd3bcbf8a271429ee31f32eaf928058ab376 /lfunc.c | |
parent | 14edd364c3abcb758e74c68a2bdd4ddaeefdae2a (diff) | |
download | lua-b4d5dff8ec4f1c8a44db66d368e95d359b04aea7.tar.gz lua-b4d5dff8ec4f1c8a44db66d368e95d359b04aea7.tar.bz2 lua-b4d5dff8ec4f1c8a44db66d368e95d359b04aea7.zip |
Multiple errors in '__toclose' report the first one
When there are multiple errors when closing objects, the error
reported by the protected call is the first one, for two reasons:
First, other errors may be caused by this one;
second, the first error is handled in the original execution context,
and therefore has the full traceback.
Diffstat (limited to 'lfunc.c')
-rw-r--r-- | lfunc.c | 9 |
1 files changed, 6 insertions, 3 deletions
@@ -144,13 +144,16 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { | |||
144 | luaG_runerror(L, "attempt to close non-closable variable '%s'", vname); | 144 | luaG_runerror(L, "attempt to close non-closable variable '%s'", vname); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | else { /* there was an error */ | 147 | else { /* must close the object in protected mode */ |
148 | ptrdiff_t oldtop = savestack(L, level + 1); | ||
148 | /* save error message and set stack top to 'level + 1' */ | 149 | /* save error message and set stack top to 'level + 1' */ |
149 | luaD_seterrorobj(L, status, level); | 150 | luaD_seterrorobj(L, status, level); |
150 | if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ | 151 | if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ |
151 | int newstatus = luaD_pcall(L, callclose, NULL, savestack(L, level), 0); | 152 | int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); |
152 | if (newstatus != LUA_OK) /* another error when closing? */ | 153 | if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ |
153 | status = newstatus; /* this will be the new error */ | 154 | status = newstatus; /* this will be the new error */ |
155 | else /* leave original error (or nil) on top */ | ||
156 | L->top = restorestack(L, oldtop); | ||
154 | } | 157 | } |
155 | /* else no metamethod; ignore this case and keep original error */ | 158 | /* else no metamethod; ignore this case and keep original error */ |
156 | } | 159 | } |