Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asynchronously release SymbolicExpression #149

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

RodolpheDuge
Copy link

Hello !

We are currently working with RDotNet 1.9.0 / R 4.1.2 / .NET Framework 4.7 / Windows ,
but we have had some strange behaviour, our process was randomly stucked on a RDotNet method call but inside the R.dll
(active loop, 100% CPU load)
Here is a part of the stack:

R.dll!Rf_pmatch+0x32da
R.dll!Rf_allocVector3+0x2d0
R.dll!Rf_allocMatrix+0x36
R.dll!rwarn_+0xa1c6
R.dll!rwarn_+0xfe0c
R.dll!R_BadLongVector+0x17f
R.dll!R_initAssignSymbols+0x745b
R.dll!Rf_eval+0x171

For an unknown reason (compilation option?) the symbols were not correct, so after a few logs added in r.dll
It appears that R was stucked in r-source/src/main/memory.c/RunGenCollect

Not always exactly the same line, but it looked like some kind of corruption of R internal structure
After a "few" other tests, it was finally reproducible more often (see CreateStressTest below)
It is a quick loop of REngine.Evaluate which often gives AccessViolationException or sometimes it is stucked in the R garbage step.

The problem seems to come from SymbolicExpression.
Preserve method is called in constructor and_Unpreserve_ method is called in the ReleaseHandle,
but as it is a SafeHandle and Dispose is never called, ReleaseHandle method is called in another thread of the VM which is dedicated to finalization process.
So we may have 2 different threads accessing the R.dll

Unfortunately, in Expression.TryEvaluate there is a call to R_tryEval from R.dll which is not locked.
And since R-4.1.2 there has been changes in R_tryEval (now it uses R_PreserveObject and R_ReleaseObject)

It happens with R-4.1.2 / R-4.0.2 (windows and linux version)

So here is a possible fix:
add a lock on Expression.TryEvaluate,
as we dont want to lock and block the GC Finalizer thread for a long time, do the release in another thread.

Another possible fix could have been to explictly call Dispose on each SymbolicExpression (so they cant be called from another thread) and that the caller of REngin.Evaluate do the same with the SymbolicExpression result)
But there are a lot of SymbolicExpression creation and maybe it would be less readable, for example in Parse method:

  • to get the Nil value
  • to get an element of a VectorExpression
  • to get an environment
  • for each R statement in string

It could be the same issue than here: #133

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant