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

Fix segfault in variables tests #641

Merged
merged 3 commits into from
Nov 27, 2024
Merged

Fix segfault in variables tests #641

merged 3 commits into from
Nov 27, 2024

Conversation

dfalbel
Copy link
Contributor

@dfalbel dfalbel commented Nov 25, 2024

With current main, running:

cargo test -p ark --lib variables::variable::tests::test_truncation

Will eventually fail with:

Error: VECTOR_ELT() can only be applied to a 'list', not a 'symbol'
Fatal error: unable to initialize the JIT

While I'm not entirely sure what's happenning, I believe this is a protection issue, and this PR seems to fix the problem.

@dfalbel dfalbel requested a review from lionel- November 25, 2024 22:15
Comment on lines 1867 to 1868
env.bind("x".into(), harp::parse_eval_base(code).unwrap());
let value = harp::parse_eval_base(code).unwrap();
env.bind("x".into(), value.sexp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what was happening is that with:

env.bind("x".into(), harp::parse_eval_base(code).unwrap());
  • harp::parse_eval_base(code).unwrap() creates a RObject which does protection
  • env.bind() consumes value: impl Into<SEXP>, and calls value.into() on value. This consumes the RObject (dropping and unprotecting it) and returns the unprotected SEXP
  • The unprotected SEXP is then used in Rf_defineVar()

In theory it seems like Rf_defineVar() shouldn't do anything to trigger a reallocation, but in practice we see this crash.


More broadly I think this suggests a typing issue with RObject. I feel like its probably quite bad that we allow the underlying SEXP to escape the lifetime of RObject so easily. It's like we need to tie the lifetime of RObject to the lifetime of underlying SEXP unless you call something super explicit like unsafe into_sexp() which has a SAFETY note that you are taking protection ownership over the SEXP from here on out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the impl Into<SEXP> wouldn't work because we could just write temporary().sexp right? hmm....

I wonder if .sexp should return a 'SEXP instead of a SEXP.
I was also thinking that view() should do the same to tie the lifetimes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing impl Into<SEXP> seems to fix the problem as it seems temporary() is only deleted after the function execution. At least that what I can tell from something like:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dca6608de1df2f3b16ba2c2a217aedf3

Copy link
Contributor

@lionel- lionel- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also remove the impl Into<SEXP> to reduce the footgun factor please?

Comment on lines 1867 to 1868
env.bind("x".into(), harp::parse_eval_base(code).unwrap());
let value = harp::parse_eval_base(code).unwrap();
env.bind("x".into(), value.sexp);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the impl Into<SEXP> wouldn't work because we could just write temporary().sexp right? hmm....

I wonder if .sexp should return a 'SEXP instead of a SEXP.
I was also thinking that view() should do the same to tie the lifetimes.

@@ -91,13 +91,13 @@ impl Environment {
std::iter::successors(Some(self.clone()), |p| p.parent())
}

pub fn bind(&self, name: RSymbol, value: impl Into<SEXP>) {
pub fn bind(&self, name: RSymbol, value: SEXP) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm or maybe make it take an &RObject?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 94eba52

@dfalbel dfalbel merged commit 7af2c44 into main Nov 27, 2024
6 checks passed
@dfalbel dfalbel deleted the bugfix/test-failures branch November 27, 2024 14:23
@github-actions github-actions bot locked and limited conversation to collaborators Nov 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants