lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Feb 09, 2007 at 03:29:57PM -0500, Rici Lake wrote:
>>There is pcall() ('try') without 'finally' to properly free resources in the
>>called functions.  What do you think about adding the optionally finally block
>>statement to functions?  This finally block must be executed once whenever
>>returned from function or error throwed.

> Now, we might have different views about what should happen if a thread 
> yields; in essence, we certainly want finalizers to run if the thread 
> is never going to be resumed, but it's hard to know that in advance. So 
> that leaves the finalizer running when/if the thread is garbage 
> collected.

I havn't understood all of the details of this idea, since I don't know
Lua's internals well enough, but what if an error is thrown?  I think
that's most of the point: to be able to clean up promptly if an error
happens.

It seems like it couldn't run the finalizer then call the error
function; errfunc needs to be called at the actual error, for
backtracing.  In principle, it could call the error handler, then
call the finalizer before returning to the nearest pcall.

A similar problem exists in C.  In one case, I want a CFunction
that does this:

        int func(lua_State *L)
        {
                object *obj = new object;
                lua_call(L, 0, 0);
                delete obj;
                return 0;
        }    

where the given function is called with "obj" existing, and "obj" is
guaranteed to be deleted before it returns.  (This sets some state,
and unsets it when deleted.)

The trouble is deleting p on error.  I can't just use lua_pcall, because
I do want errors propagated to the caller transparently.  If I pcall,
delete, then throw the error again, the error handler will get an unwound
stack.

I can't stash p in a userdata, because p can't be deleted lazily, even
on error.

It seems like changing the current errfunc would work, in principle:

        object *obj = new object;

        lua_geterrorhandler(L); // push errfunc or panic func

	lua_pushvalue(L, -1); // A
	lua_pushlightuserdata(L, obj);
	lua_pushcclosure(L, function_to_delete_obj, 2);
        lua_seterrorhandler(L);

        lua_call(L, f);

        /* if we get here, no error occurred */
        lua_seterrorhandler(L); // restore A
        delete obj;

        int function_to_delete_obj(L)
        {
	   obj = lua_touserdata(L, lua_upvalueindex(L, 1));
           delete obj;
	   lua_pushvalue(L, lua_upvalueindex(L, 2));
	   lua_call(L, lua_gettop(L)-1, LUA_MULTRET); // call the original error handler
	   return lua_gettop(L);
        }

but I have no idea about the implementation.

-- 
Glenn Maynard