Re: cdata finalizer called twice

  • From: Peter Colberg <peter@xxxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Fri, 14 Nov 2014 17:28:21 -0500

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

Other related posts: