Skip to content

A question about multiple(?) out of order ReleaseObject

6 messages · Gabriel Becker, Saptarshi Guha, Simon Urbanek

#
On Mar 6, 2014, at 5:32 PM, Saptarshi Guha <saptarshi.guha at gmail.com> wrote:

            
yes
yes (assuming the binding to v still exists at that point). Note, however, that is such a case you R_PreserveObject() is pointless since you don't need to protect it on exit (that's in fact the convention - return results are never protected).
Normally, you should not keep the result of a function protected since it means you *have* to guarantee the unprotect at a later point. That is in general impossible to guarantee unless you have another object that is holding a reference that will be cleared by an explicitly registered finalizer. So unless that is the case, you are creating an explicit leak = bad. If you don't have as stack-like design, you can always use explicitly managed object for the lifetime (personally, I prefer that) since all chained objects are protected by design, or use REPROTECT.

Cheers,
Simon
#
Hello Simon,

Thanks much for the replies. It makes sense now and I'm on the right
track. I'll explain why this
might happen.

I've written a package caller rterra [1] which essentially allows the
R user to write extensions in
Lua. The extensions are JIT compiled via LuaJIT. For deterministic
performance the user can write
their extension in Terra.

To make memory management easier for the extension writer, i wanted auto memory
management. Consider the following code sample which calls an
extension written in Lua to compute a sum
by traversing some JSON

1. In R, the extension, is called as

l <- terra("computeCountsByDayAndCountry", values, c("2013-01-01","2014-12-31"))

2. In Lua, the code looks like

function computeCountsByDayAndCountry(jsonstr,dateRange)
   local x,y = R.Robj(jsonstr),R.Robj(dateRange)
   local dstart,dend = ffi.string(y[0]),ffi.string(y[1])
   local f =  R.Robj{type='str', length =#x}
   R.autoProtect(f) -- line 'A'
   for index = 0, #x-1 do
      local ok,jc  = pcall(cjson.decode,ffi.string(x[index][0]))
      if ok then
     f[index] = cjson.encode( _computeSearchCountsCountry(jc,dstart,dend))
      else
     f[index] = cjson.encode({})
      end
   end
   return f
end

When this returns, the SEXP contained in 'f' is associated with 'l' (in step 1)

LuaJIT has garbage collection. At http://luajit.org/ext_ffi_api.html,
when 'f' above (line 'A') get
garbage collected, a finalizer is run. The call to autoProtect does

1. calls PReserveObject on f.sexp
2. sets the finalizer to call ReleaseObject.

When the user calls an extension written in Lua again, 'f' will get
garbage collected by Lua
(assuming it has no references in Lua).

And yes, there will be a mem leak, *iff* the user *never* calls an
extension written in Lua again,
otherwise no.

And of course, the user can not call autoProtect, but can manage it
themselves, i.e. using R.protect
and R.unprotect.

Thanks for the insight

http://people.mozilla.org/~sguha/blog/2013/08/01/rterra_first_post.html

Cheers
Saptarshi

On Thu, Mar 6, 2014 at 7:05 PM, Simon Urbanek
<simon.urbanek at r-project.org> wrote: