[Rd] A question about multiple(?) out of order ReleaseObject

Saptarshi Guha saptarshi.guha at gmail.com
Fri Mar 7 07:09:59 CET 2014


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:
> On Mar 6, 2014, at 5:32 PM, Saptarshi Guha <saptarshi.guha at gmail.com> wrote:
>
>> Hello,
>>
>> This  is a question that probably reveals my lack of understanding.
>> In a C function (call it cfunc), i created a SEXP, called S, and then
>> called R_PreserveObject on S.
>>
>> I returned the SEXP to the calling R function (call it rfunc). Note, I
>> didn't call
>> R_ReleaseObject on S.
>>
>> v <- .Call("cfunc")
>>
>> So, are the following  statements correct
>>
>> 1.  S is 'doubly' protected from the GC by  being associated both with 'v'
>> and because it has been added to the precious list (via a call to
>> R_PreserveObject without ReleaseObject being called)
>>
>
> yes
>
>
>> 2. I have another C function called cfunc2. In cfunc2, I call
>> R_ReleaseObject on S.  S , however, is still protected from the GC, because
>> it is associated with 'v'
>>
>
> 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).
>
>
>> Is (1) and (2) correct?
>>
>> I have not used R_protect/unprotect, because if I return from cfunc without the equivalent number of unprotects, i get 'unbalanced stack' warnings. I'd rather not have to worry about that because i intend to balance it later.
>>
>
> 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
>
>
>> Regards
>> Saptarshi
>>
>>       [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>



More information about the R-devel mailing list