diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-25 13:22:42 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-25 13:22:42 -0300 |
commit | 13635f7de7c51b26c447ce444a2c045cba83fe7c (patch) | |
tree | b9461626b368e8ca1161b01e2771447898fdecd8 | |
parent | d8a442206d2845e1749cc36dd59208428ef1d117 (diff) | |
download | lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.gz lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.tar.bz2 lua-13635f7de7c51b26c447ce444a2c045cba83fe7c.zip |
new version of protected execution
-rw-r--r-- | ldo.c | 168 | ||||
-rw-r--r-- | ldo.h | 6 | ||||
-rw-r--r-- | lstate.c | 49 | ||||
-rw-r--r-- | lstate.h | 14 | ||||
-rw-r--r-- | ltests.c | 12 |
5 files changed, 149 insertions, 100 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 1.95 2000/09/11 20:29:27 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.96 2000/09/12 13:47:39 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 | */ |
@@ -199,88 +199,60 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
199 | } | 199 | } |
200 | 200 | ||
201 | 201 | ||
202 | static void message (lua_State *L, const char *s) { | ||
203 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
204 | if (*luaO_typename(em) == 'f') { | ||
205 | *L->top = *em; | ||
206 | incr_top; | ||
207 | lua_pushstring(L, s); | ||
208 | luaD_call(L, L->top-2, 0); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | |||
213 | void luaD_breakrun (lua_State *L, int errcode) { | ||
214 | if (L->errorJmp) { | ||
215 | L->errorJmp->status = errcode; | ||
216 | longjmp(L->errorJmp->b, 1); | ||
217 | } | ||
218 | else { | ||
219 | if (errcode != LUA_ERRMEM) | ||
220 | message(L, "unable to recover; exiting\n"); | ||
221 | exit(EXIT_FAILURE); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /* | 202 | /* |
226 | ** Reports an error, and jumps up to the available recovery label | 203 | ** Execute a protected call. |
227 | */ | 204 | */ |
228 | void lua_error (lua_State *L, const char *s) { | 205 | struct CallS { /* data to `f_call' */ |
229 | if (s) message(L, s); | 206 | StkId func; |
230 | luaD_breakrun(L, LUA_ERRRUN); | 207 | int nresults; |
231 | } | 208 | }; |
232 | 209 | ||
233 | 210 | static void f_call (lua_State *L, void *ud) { | |
234 | static void chain_longjmp (lua_State *L, struct lua_longjmp *lj) { | 211 | struct CallS *c = (struct CallS *)ud; |
235 | lj->status = 0; | 212 | luaD_call(L, c->func, c->nresults); |
236 | lj->base = L->Cbase; | ||
237 | lj->previous = L->errorJmp; | ||
238 | L->errorJmp = lj; | ||
239 | } | 213 | } |
240 | 214 | ||
241 | 215 | ||
242 | static int restore_longjmp (lua_State *L, struct lua_longjmp *lj) { | 216 | int lua_call (lua_State *L, int nargs, int nresults) { |
243 | L->Cbase = lj->base; | 217 | StkId func = L->top - (nargs+1); /* function to be called */ |
244 | L->errorJmp = lj->previous; | 218 | struct CallS c; |
245 | return lj->status; | 219 | int status; |
220 | c.func = func; c.nresults = nresults; | ||
221 | status = luaD_runprotected(L, f_call, &c); | ||
222 | if (status != 0) /* an error occurred? */ | ||
223 | L->top = func; /* remove parameters from the stack */ | ||
224 | return status; | ||
246 | } | 225 | } |
247 | 226 | ||
248 | 227 | ||
249 | /* | 228 | /* |
250 | ** Execute a protected call. | 229 | ** Execute a protected parser. |
251 | */ | 230 | */ |
252 | int lua_call (lua_State *L, int nargs, int nresults) { | 231 | struct ParserS { /* data to `f_parser' */ |
253 | StkId func = L->top - (nargs+1); /* function to be called */ | 232 | ZIO *z; |
254 | struct lua_longjmp myErrorJmp; | 233 | int bin; |
255 | chain_longjmp(L, &myErrorJmp); | 234 | }; |
256 | if (setjmp(myErrorJmp.b) == 0) { | 235 | |
257 | luaD_call(L, func, nresults); | 236 | static void f_parser (lua_State *L, void *ud) { |
258 | } | 237 | struct ParserS *p = (struct ParserS *)ud; |
259 | else { /* an error occurred: restore the state */ | 238 | Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); |
260 | L->top = func; /* remove garbage from the stack */ | 239 | luaV_Lclosure(L, tf, 0); |
261 | restore_stack_limit(L); | ||
262 | } | ||
263 | return restore_longjmp(L, &myErrorJmp); | ||
264 | } | 240 | } |
265 | 241 | ||
266 | 242 | ||
267 | static int protectedparser (lua_State *L, ZIO *z, int bin) { | 243 | static int protectedparser (lua_State *L, ZIO *z, int bin) { |
268 | struct lua_longjmp myErrorJmp; | 244 | struct ParserS p; |
269 | unsigned long old_blocks; | 245 | unsigned long old_blocks; |
246 | int status; | ||
247 | p.z = z; p.bin = bin; | ||
270 | luaC_checkGC(L); | 248 | luaC_checkGC(L); |
271 | old_blocks = L->nblocks; | 249 | old_blocks = L->nblocks; |
272 | chain_longjmp(L, &myErrorJmp); | 250 | status = luaD_runprotected(L, f_parser, &p); |
273 | if (setjmp(myErrorJmp.b) == 0) { | 251 | if (status == LUA_ERRRUN) /* an error occurred: correct error code */ |
274 | Proto *tf = bin ? luaU_undump(L, z) : luaY_parser(L, z); | 252 | status = LUA_ERRSYNTAX; |
275 | luaV_Lclosure(L, tf, 0); | ||
276 | } | ||
277 | else { /* an error occurred: correct error code */ | ||
278 | if (myErrorJmp.status == LUA_ERRRUN) | ||
279 | myErrorJmp.status = LUA_ERRSYNTAX; | ||
280 | } | ||
281 | /* add new memory to threshould (as it probably will stay) */ | 253 | /* add new memory to threshould (as it probably will stay) */ |
282 | L->GCthreshold += (L->nblocks - old_blocks); | 254 | L->GCthreshold += (L->nblocks - old_blocks); |
283 | return restore_longjmp(L, &myErrorJmp); /* error code */ | 255 | return status; |
284 | } | 256 | } |
285 | 257 | ||
286 | 258 | ||
@@ -339,3 +311,71 @@ int lua_dostring (lua_State *L, const char *str) { | |||
339 | return lua_dobuffer(L, str, strlen(str), str); | 311 | return lua_dobuffer(L, str, strlen(str), str); |
340 | } | 312 | } |
341 | 313 | ||
314 | |||
315 | /* | ||
316 | ** {====================================================== | ||
317 | ** Error-recover functions (based on long jumps) | ||
318 | ** ======================================================= | ||
319 | */ | ||
320 | |||
321 | /* chain list of long jump buffers */ | ||
322 | struct lua_longjmp { | ||
323 | jmp_buf b; | ||
324 | struct lua_longjmp *previous; | ||
325 | volatile int status; /* error code */ | ||
326 | }; | ||
327 | |||
328 | |||
329 | static void message (lua_State *L, const char *s) { | ||
330 | const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); | ||
331 | if (*luaO_typename(em) == 'f') { | ||
332 | *L->top = *em; | ||
333 | incr_top; | ||
334 | lua_pushstring(L, s); | ||
335 | luaD_call(L, L->top-2, 0); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | |||
340 | /* | ||
341 | ** Reports an error, and jumps up to the available recovery label | ||
342 | */ | ||
343 | void lua_error (lua_State *L, const char *s) { | ||
344 | if (s) message(L, s); | ||
345 | luaD_breakrun(L, LUA_ERRRUN); | ||
346 | } | ||
347 | |||
348 | |||
349 | void luaD_breakrun (lua_State *L, int errcode) { | ||
350 | if (L->errorJmp) { | ||
351 | L->errorJmp->status = errcode; | ||
352 | longjmp(L->errorJmp->b, 1); | ||
353 | } | ||
354 | else { | ||
355 | if (errcode != LUA_ERRMEM) | ||
356 | message(L, "unable to recover; exiting\n"); | ||
357 | exit(EXIT_FAILURE); | ||
358 | } | ||
359 | } | ||
360 | |||
361 | |||
362 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { | ||
363 | StkId oldCbase = L->Cbase; | ||
364 | StkId oldtop = L->top; | ||
365 | struct lua_longjmp lj; | ||
366 | lj.status = 0; | ||
367 | lj.previous = L->errorJmp; /* chain new error handler */ | ||
368 | L->errorJmp = &lj; | ||
369 | if (setjmp(lj.b) == 0) | ||
370 | (*f)(L, ud); | ||
371 | else { /* an error occurred: restore the state */ | ||
372 | L->Cbase = oldCbase; | ||
373 | L->top = oldtop; | ||
374 | restore_stack_limit(L); | ||
375 | } | ||
376 | L->errorJmp = lj.previous; /* restore old error handler */ | ||
377 | return lj.status; | ||
378 | } | ||
379 | |||
380 | /* }====================================================== */ | ||
381 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.h,v 1.23 2000/08/28 17:57:04 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 1.24 2000/08/29 14:48:16 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 | */ |
@@ -24,8 +24,10 @@ void luaD_adjusttop (lua_State *L, StkId base, int extra); | |||
24 | void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); | 24 | void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); |
25 | void luaD_call (lua_State *L, StkId func, int nResults); | 25 | void luaD_call (lua_State *L, StkId func, int nResults); |
26 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); | 26 | void luaD_callTM (lua_State *L, const TObject *f, int nParams, int nResults); |
27 | void luaD_breakrun (lua_State *L, int errcode); | ||
28 | void luaD_checkstack (lua_State *L, int n); | 27 | void luaD_checkstack (lua_State *L, int n); |
29 | 28 | ||
29 | void luaD_breakrun (lua_State *L, int errcode); | ||
30 | int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); | ||
31 | |||
30 | 32 | ||
31 | #endif | 33 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.39 2000/09/12 18:42:32 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.40 2000/09/21 14:41:25 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | #ifdef DEBUG | 22 | #ifdef DEBUG |
23 | extern lua_State *lua_state; | 23 | static lua_State *lua_state = NULL; |
24 | void luaB_opentests (lua_State *L); | 24 | void luaB_opentests (lua_State *L); |
25 | #endif | 25 | #endif |
26 | 26 | ||
@@ -38,8 +38,29 @@ static int errormessage (lua_State *L) { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | 40 | ||
41 | /* | ||
42 | ** open parts that may cause memory-allocation errors | ||
43 | */ | ||
44 | static void f_luaopen (lua_State *L, void *ud) { | ||
45 | int stacksize = *(int *)ud; | ||
46 | if (stacksize == 0) | ||
47 | stacksize = DEFAULT_STACK_SIZE; | ||
48 | else | ||
49 | stacksize += LUA_MINSTACK; | ||
50 | L->gt = luaH_new(L, 10); | ||
51 | luaD_init(L, stacksize); | ||
52 | luaS_init(L); | ||
53 | luaX_init(L); | ||
54 | luaT_init(L); | ||
55 | lua_register(L, LUA_ERRORMESSAGE, errormessage); | ||
56 | #ifdef DEBUG | ||
57 | luaB_opentests(L); | ||
58 | if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ | ||
59 | #endif | ||
60 | } | ||
61 | |||
62 | |||
41 | lua_State *lua_open (int stacksize) { | 63 | lua_State *lua_open (int stacksize) { |
42 | struct lua_longjmp myErrorJmp; | ||
43 | lua_State *L = luaM_new(NULL, lua_State); | 64 | lua_State *L = luaM_new(NULL, lua_State); |
44 | if (L == NULL) return NULL; /* memory allocation error */ | 65 | if (L == NULL) return NULL; /* memory allocation error */ |
45 | L->stack = NULL; | 66 | L->stack = NULL; |
@@ -62,26 +83,14 @@ lua_State *lua_open (int stacksize) { | |||
62 | L->callhook = NULL; | 83 | L->callhook = NULL; |
63 | L->linehook = NULL; | 84 | L->linehook = NULL; |
64 | L->allowhooks = 1; | 85 | L->allowhooks = 1; |
65 | L->errorJmp = &myErrorJmp; | 86 | L->errorJmp = NULL; |
66 | if (setjmp(myErrorJmp.b) == 0) { /* to catch memory allocation errors */ | 87 | if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) { |
67 | L->gt = luaH_new(L, 10); | 88 | /* memory allocation error: free partial state */ |
68 | luaD_init(L, (stacksize == 0) ? DEFAULT_STACK_SIZE : | ||
69 | stacksize+LUA_MINSTACK); | ||
70 | luaS_init(L); | ||
71 | luaX_init(L); | ||
72 | luaT_init(L); | ||
73 | lua_register(L, LUA_ERRORMESSAGE, errormessage); | ||
74 | #ifdef DEBUG | ||
75 | luaB_opentests(L); | ||
76 | #endif | ||
77 | L->GCthreshold = L->nblocks*4; | ||
78 | L->errorJmp = NULL; | ||
79 | return L; | ||
80 | } | ||
81 | else { /* memory allocation error: free partial state */ | ||
82 | lua_close(L); | 89 | lua_close(L); |
83 | return NULL; | 90 | return NULL; |
84 | } | 91 | } |
92 | L->GCthreshold = L->nblocks*4; | ||
93 | return L; | ||
85 | } | 94 | } |
86 | 95 | ||
87 | 96 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 1.37 2000/08/28 17:57:04 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.38 2000/09/11 17:38:42 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -7,8 +7,6 @@ | |||
7 | #ifndef lstate_h | 7 | #ifndef lstate_h |
8 | #define lstate_h | 8 | #define lstate_h |
9 | 9 | ||
10 | #include <setjmp.h> | ||
11 | |||
12 | #include "lobject.h" | 10 | #include "lobject.h" |
13 | #include "lua.h" | 11 | #include "lua.h" |
14 | #include "luadebug.h" | 12 | #include "luadebug.h" |
@@ -33,15 +31,7 @@ struct Ref { | |||
33 | }; | 31 | }; |
34 | 32 | ||
35 | 33 | ||
36 | /* | 34 | struct lua_longjmp; /* defined in ldo.c */ |
37 | ** chain list of long jumps | ||
38 | */ | ||
39 | struct lua_longjmp { | ||
40 | jmp_buf b; | ||
41 | struct lua_longjmp *previous; | ||
42 | volatile int status; /* error code */ | ||
43 | StkId base; | ||
44 | }; | ||
45 | 35 | ||
46 | 36 | ||
47 | typedef struct stringtable { | 37 | typedef struct stringtable { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 1.42 2000/09/14 14:09:31 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.43 2000/09/25 14:48:42 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -422,11 +422,19 @@ static int testC (lua_State *L) { | |||
422 | else if EQ("concat") { | 422 | else if EQ("concat") { |
423 | lua_concat(L, getnum); | 423 | lua_concat(L, getnum); |
424 | } | 424 | } |
425 | else if EQ("call") { | 425 | else if EQ("rawcall") { |
426 | int narg = getnum; | 426 | int narg = getnum; |
427 | int nres = getnum; | 427 | int nres = getnum; |
428 | lua_rawcall(L, narg, nres); | 428 | lua_rawcall(L, narg, nres); |
429 | } | 429 | } |
430 | else if EQ("call") { | ||
431 | int narg = getnum; | ||
432 | int nres = getnum; | ||
433 | lua_call(L, narg, nres); | ||
434 | } | ||
435 | else if EQ("dostring") { | ||
436 | lua_dostring(L, luaL_check_string(L, getnum)); | ||
437 | } | ||
430 | else if EQ("type") { | 438 | else if EQ("type") { |
431 | lua_pushstring(L, lua_type(L, getnum)); | 439 | lua_pushstring(L, lua_type(L, getnum)); |
432 | } | 440 | } |