On Thu, Nov 13, 2014 at 10:58:49PM -0500, Peter Colberg wrote: > After some experimentation I found that duplicate finalization occurs > only when ffi.gc() is both compiled and invoked in a tail call. > > This method of constructing objects works fine: > > ffi.cdef[[typedef struct _cl_event *cl_event;]] > > local event_ptr = ffi.new("cl_event[1]") > > local function enqueue_marker(queue) > assert(C.CL_SUCCESS == C.clEnqueueMarker(queue, event_ptr)) > local event = ffi.gc(event_ptr[0], release_event) -- no tail call > return event > end > > This method of constructing objects causes duplicate finalization: > > local function enqueue_marker(queue) > assert(C.CL_SUCCESS == C.clEnqueueMarker(queue, event_ptr)) > return ffi.gc(event_ptr[0], release_event) -- tail call > end To confirm that the tail call is exposing this behaviour: Finalization works fine if the tail call is avoided using () local function enqueue_marker(queue) assert(C.CL_SUCCESS == C.clEnqueueMarker(queue, event_ptr)) return (ffi.gc(event_ptr[0], release_event)) end or if the finalizer is set outside of the function local function enqueue_marker(queue) assert(C.CL_SUCCESS == C.clEnqueueMarker(queue, event_ptr)) return event_ptr end -- repeated calls in program loop ffi.gc(enqueue_marker(queue)[0], release_event) Peter