[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: lua calling exit()
- From: "Eric Ries" <eries@...>
- Date: Tue, 21 Aug 2001 14:00:05 -0700
FWIW, I use a C++ class to encapsulate all my C++/Lua interactions. On each
method on this class, I have macros that assert zero stack growth and (in
release mode) adjust the stack correctly. This has alleviated all such
problems from our code base.
Eric
> -----Original Message-----
> From: owner-lua-l@tecgraf.puc-rio.br
> [mailto:owner-lua-l@tecgraf.puc-rio.br]On Behalf Of Bruno Silva
> Sent: Tuesday, August 21, 2001 1:40 PM
> To: Multiple recipients of list
> Subject: RE: lua calling exit()
>
>
> > > I have a newbie question then: how should I call this function in an
> > > *error-proof* way?
> > >
> > > -- takes 2 strings, returns a boolean
> > > handled = Function (arg1, arg2)
> > >
> > > // calls Function
> > > lua_getglobal(s_lua, "Function");
> > > lua_pushstring (s_lua, arg1);
> > > lua_pushstring (s_lua, arg2);
> > > if (lua_call (s_lua, 2, 1) == 0)
> > > {
> > > handled = (bool) lua_tonumber (s_lua, -1);
> > > lua_pop (s_lua, 1);
> > > }
> >
> > That is difficult. lua_getglobal, lua_pushstring and lua_tonumber
> > may raise an error. Even lua_pushcfunction/cclosure may raise one
> > so it's pretty difficult to call something in a secure way. A
> > lua_catch function (similar to luaD_runprotected) would help a lot.
> >
> This is unfortunate. As Luiz pointed out though, this is less of a
> problem when the functions being called are written in Lua. So is the
> following any safer?
>
> lua_dostring (L, "return Function (arg1, arg2)");
>
> This leaves whatever values "Function" returns on the stack and would
> allow leaking if Function is not properly written.
>
> Luiz wrote:
> > >This must work (i.e., leave a clean stack) regardless of what
> > >"Function" evaluates to and whether the execution of "Function"
> > >succeeded or failed for whatever reasons.
> >
> > If you need this, I think the simplest solution is use lua_rawcall
> instead > of lua_call (same arguments, but lua_rawcall is void). In this
> case, if
> > "Function" fails, then you'll get an ordinary error through
> _ERRORMESSAGE.
> >
> Well, it then immediately calls exit() on my app. Are you assuming that
> the lua_rawcall is itself protected by the lua_call() trick? If so, then
> I guess it would work.
>
> Thanks for all the info. Bottom line for me so far is that we need to be
> extra careful with the stack. Lua can kill the app mercilessly when a
> stack overflow occurs, which is unacceptable for us, so we need to wrap
> all Lua API usage with a lua_call. I am planning to write a convenience
> class that provides this behavior, and change the Lua sources to make
> sure no Lua API calls can happen outside this context (that is, one that
> doesn't have a setjmp to jump back to).
>
> Is it possible to handle breakrun's in a different manner, even if it
> involves dumping the entire Lua context?
>
> In case anybody cares, I threw the following class together to help
> reduce the occurrence of these problems. It fairly simple and certainly
> not fail proof but helps catching certain careless uses of the stack.
>
> Bruno
>
> //
> // This class helps control lua stack leaks and underflows, use as:
> // { LUA_SAFE_STACK_BLOCK(L); /* any lua code */ }
>
> #define LUA_MAKE_BLOCK_NAME(x) _LUA_BLOCK_NAME_##x##_
> // __COUNTER__ is MS specific, but you don't really need it
> #define LUA_SAFE_STACK_BLOCK(LuaState) CLuaSafeStack
> LUA_MAKE_BLOCK_NAME(__COUNTER__) (LuaState)
>
> class CLuaSafeStack
> {
> public:
> CLuaSafeStack (lua_State* L)
> : m_lua (L)
> {
> m_top = lua_gettop (m_lua);
> if (m_top < 0)
> {
> ASSERTMSG (false, _T("Lua stack underflow, fixed"));
> m_top = 0;
> lua_settop (m_lua, m_top);
> }
> }
>
> ~CLuaSafeStack (void)
> {
> int endtop = lua_gettop (m_lua);
> if (endtop != m_top) // stack leak
> {
> if (endtop < 0)
> ASSERTMSG (false, _T("Lua stack underflow, fixed"));
> else
> ASSERTMSG (false, _T("Lua stack leak, cleaned up"));
> // fix the stack to avoid any leaks (should not be
> needed)
> lua_settop (m_lua, m_top);
> }
> }
> protected:
> lua_State* m_lua;
> int m_top;
> };