diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-04 16:38:35 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-04 16:38:35 -0300 |
commit | 435f587ed05e2c4d542e1db9ae9e4efbb7e02305 (patch) | |
tree | 1b179bf836cfdaf8ed74df24c2d22cda8f07aaa9 /ldo.c | |
parent | ae55f3eeada102f3fa8345173410feaf1db42cde (diff) | |
download | lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.tar.gz lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.tar.bz2 lua-435f587ed05e2c4d542e1db9ae9e4efbb7e02305.zip |
(much) better handling of memory alloction errors
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 94 |
1 files changed, 52 insertions, 42 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.80 2000/06/26 19:28:31 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.81 2000/06/28 20:20:36 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 | */ |
@@ -237,17 +237,41 @@ static void message (lua_State *L, const char *s) { | |||
237 | } | 237 | } |
238 | } | 238 | } |
239 | 239 | ||
240 | |||
241 | void luaD_breakrun (lua_State *L, int errcode) { | ||
242 | if (L->errorJmp) { | ||
243 | L->errorJmp->status = errcode; | ||
244 | longjmp(L->errorJmp->b, 1); | ||
245 | } | ||
246 | else { | ||
247 | if (errcode != LUA_ERRMEM) | ||
248 | message(L, "unable to recover; exiting\n"); | ||
249 | exit(1); | ||
250 | } | ||
251 | } | ||
252 | |||
240 | /* | 253 | /* |
241 | ** Reports an error, and jumps up to the available recovery label | 254 | ** Reports an error, and jumps up to the available recovery label |
242 | */ | 255 | */ |
243 | void lua_error (lua_State *L, const char *s) { | 256 | void lua_error (lua_State *L, const char *s) { |
244 | if (s) message(L, s); | 257 | if (s) message(L, s); |
245 | if (L->errorJmp) | 258 | luaD_breakrun(L, LUA_ERRRUN); |
246 | longjmp(L->errorJmp->b, 1); | 259 | } |
247 | else { | 260 | |
248 | message(L, "unable to recover; exiting\n"); | 261 | |
249 | exit(1); | 262 | static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { |
250 | } | 263 | lj->base = L->Cstack.base; |
264 | lj->numCblocks = L->numCblocks; | ||
265 | lj->previous = L->errorJmp; | ||
266 | L->errorJmp = lj; | ||
267 | } | ||
268 | |||
269 | |||
270 | static void restore_longjmp (lua_State *L, struct lua_longjmp *lj) { | ||
271 | L->Cstack.num = 0; /* no results */ | ||
272 | L->top = L->Cstack.base = L->Cstack.lua2C = lj->base; | ||
273 | L->numCblocks = lj->numCblocks; | ||
274 | L->errorJmp = lj->previous; | ||
251 | } | 275 | } |
252 | 276 | ||
253 | 277 | ||
@@ -257,58 +281,44 @@ void lua_error (lua_State *L, const char *s) { | |||
257 | */ | 281 | */ |
258 | int luaD_protectedrun (lua_State *L) { | 282 | int luaD_protectedrun (lua_State *L) { |
259 | struct lua_longjmp myErrorJmp; | 283 | struct lua_longjmp myErrorJmp; |
260 | StkId base = L->Cstack.base; | 284 | chain_longjmp(L, &myErrorJmp); |
261 | int numCblocks = L->numCblocks; | ||
262 | int status; | ||
263 | struct lua_longjmp *volatile oldErr = L->errorJmp; | ||
264 | L->errorJmp = &myErrorJmp; | ||
265 | if (setjmp(myErrorJmp.b) == 0) { | 285 | if (setjmp(myErrorJmp.b) == 0) { |
286 | StkId base = L->Cstack.base; | ||
266 | luaD_call(L, base, MULT_RET); | 287 | luaD_call(L, base, MULT_RET); |
267 | L->Cstack.lua2C = base; /* position of the new results */ | 288 | L->Cstack.lua2C = base; /* position of the new results */ |
268 | L->Cstack.num = L->top - base; | 289 | L->Cstack.num = L->top - base; |
269 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ | 290 | L->Cstack.base = base + L->Cstack.num; /* incorporate results on stack */ |
270 | status = 0; | 291 | L->errorJmp = myErrorJmp.previous; |
292 | return 0; | ||
271 | } | 293 | } |
272 | else { /* an error occurred: restore the stack */ | 294 | else { /* an error occurred: restore the stack */ |
273 | L->Cstack.num = 0; /* no results */ | 295 | restore_longjmp(L, &myErrorJmp); |
274 | L->top = L->Cstack.base = L->Cstack.lua2C = base; | ||
275 | L->numCblocks = numCblocks; | ||
276 | restore_stack_limit(L); | 296 | restore_stack_limit(L); |
277 | status = 1; | 297 | return myErrorJmp.status; |
278 | } | 298 | } |
279 | L->errorJmp = oldErr; | ||
280 | return status; | ||
281 | } | 299 | } |
282 | 300 | ||
283 | 301 | ||
284 | /* | 302 | /* |
285 | ** returns 0 = chunk loaded; 1 = error; 2 = no more chunks to load | 303 | ** returns 0 = chunk loaded; >0 : error; -1 = no more chunks to load |
286 | */ | 304 | */ |
287 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 305 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
288 | struct lua_longjmp myErrorJmp; | 306 | struct lua_longjmp myErrorJmp; |
289 | StkId base = L->Cstack.base; | 307 | chain_longjmp(L, &myErrorJmp); |
290 | int numCblocks = L->numCblocks; | 308 | L->top = L->Cstack.base; /* clear C2Lua */ |
291 | int status; | ||
292 | Proto *volatile tf; | ||
293 | struct lua_longjmp *volatile oldErr = L->errorJmp; | ||
294 | L->errorJmp = &myErrorJmp; | ||
295 | L->top = base; /* clear C2Lua */ | ||
296 | if (setjmp(myErrorJmp.b) == 0) { | 309 | if (setjmp(myErrorJmp.b) == 0) { |
297 | tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); | 310 | Proto *tf = bin ? luaU_undump1(L, z) : luaY_parser(L, z); |
298 | status = 0; | 311 | L->errorJmp = myErrorJmp.previous; |
312 | if (tf == NULL) return -1; /* `natural' end */ | ||
313 | luaV_Lclosure(L, tf, 0); | ||
314 | return 0; | ||
299 | } | 315 | } |
300 | else { /* an error occurred: restore Cstack and top */ | 316 | else { /* an error occurred */ |
301 | L->Cstack.num = 0; /* no results */ | 317 | restore_longjmp(L, &myErrorJmp); |
302 | L->top = L->Cstack.base = L->Cstack.lua2C = base; | 318 | if (myErrorJmp.status == LUA_ERRRUN) |
303 | L->numCblocks = numCblocks; | 319 | myErrorJmp.status = LUA_ERRSYNTAX; |
304 | tf = NULL; | 320 | return myErrorJmp.status; /* error code */ |
305 | status = 1; | ||
306 | } | 321 | } |
307 | L->errorJmp = oldErr; | ||
308 | if (status) return 1; /* error code */ | ||
309 | if (tf == NULL) return 2; /* `natural' end */ | ||
310 | luaV_Lclosure(L, tf, 0); | ||
311 | return 0; | ||
312 | } | 322 | } |
313 | 323 | ||
314 | 324 | ||
@@ -320,8 +330,8 @@ static int do_main (lua_State *L, ZIO *z, int bin) { | |||
320 | luaC_checkGC(L); | 330 | luaC_checkGC(L); |
321 | old_blocks = L->nblocks; | 331 | old_blocks = L->nblocks; |
322 | status = protectedparser(L, z, bin); | 332 | status = protectedparser(L, z, bin); |
323 | if (status == 1) return 1; /* error */ | 333 | if (status > 0) return status; /* error */ |
324 | else if (status == 2) return 0; /* `natural' end */ | 334 | else if (status < 0) return 0; /* `natural' end */ |
325 | else { | 335 | else { |
326 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); | 336 | unsigned long newelems2 = 2*(L->nblocks-old_blocks); |
327 | L->GCthreshold += newelems2; | 337 | L->GCthreshold += newelems2; |