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

A more robust solution might be to add a lifetime directly to ScipPtr. So have OwnedScip and ScipRef<'a> instead of the consumed field. #151

Closed
mmghannam opened this issue Sep 13, 2024 · 8 comments

Comments

@mmghannam
Copy link
Member

          A more robust solution might be to add a lifetime directly to `ScipPtr`. So have `OwnedScip` and `ScipRef<'a>` instead of the `consumed` field.

Originally posted by @Andful in #149 (comment)

@Andful
Copy link

Andful commented Sep 17, 2024

Oh, was not expecting the pull request to be merged without sparking any discussion.

I am a bit busy currently to implement this , but maybe, just to get an idea of the scope, I have a few questions:

  • What is the purpose of clone_for_plugin? From my understanding it is used in callbacks to query model information, e.g. during branching.
  • Is it needed? I think, as of now, it suffers from the same problems as in segfault (use after free) when accessing solution after model is dropped #138 (By accessing the clone after the main model is dropped). I think it might be better just to remove it all together. If someone wants a shallow-copy(or a reference), the user can either choose to use a reference (&Model) or a reference-counting pointer (Rc<Model> & Arc<Model>).
  • Would it be fine to remove it (given that I fix the tests)? It would be an API breaking change :/, and some users might not love it.

@mmghannam
Copy link
Member Author

  • What is the purpose of clone_for_plugin? From my understanding it is used in callbacks to query model information, e.g. during branching.

Yes your understanding is correct.

  • Is it needed? I think, as of now, it suffers from the same problems as in segfault (use after free) when accessing solution after model is dropped #138 (By accessing the clone after the main model is dropped). I think it might be better just to remove it all together. If someone wants a shallow-copy(or a reference), the user can either choose to use a reference (&Model) or a reference-counting pointer (Rc<Model> & Arc<Model>).
  • Would it be fine to remove it (given that I fix the tests)? It would be an API breaking change :/, and some users might not love it.

I don't mind removing it at all, as long as access to the SICP model is still allowed from plugins (callbacks).

Sorry for the late reply and thank you so much for your efforts!

@mmghannam
Copy link
Member Author

@Andful what do you think about wrapping up ScipPtr in an Arc and passing it around every thing that has a reference to the model, and changing all ScipPtr methods to use only immutable reference, since they are anyway can be protected from the Models methods. Then that should eliminate the use after free errors and would not need lifetimes? do you foresee any issues with this?

@Andful
Copy link

Andful commented Oct 13, 2024

That seems like a much easier solution. Was contemplating that. I have to think about it a bit. We can defer freeing to be done by ScipPtr, What is the function of vars and conss in e.g. Solution?

@mmghannam
Copy link
Member Author

I have started implementing this on the branch arc-scipptr if you want to take a look.

What is the function of vars and conss in e.g. Solution?

I assume you mean in the Model states not the solution, it's to avoid creating structs for variables and constraints every time the user queries them. But now I'm actually rethinking this I think the rust compiler could optimize that away, and would remove this internal state that needs to be kept up to date. Anyhow, that's a separate issue.

@Andful
Copy link

Andful commented Oct 14, 2024

I cannot see the branch. But feel free to ping me if you make a pull request. I was asking about vars and conss because they are freed by Model. If we let scipptr free the model and the variables on the C side, we just have to be a bit careful that vars and conss are not used after free or double freed.

Regarding Arc<ScipPtr>, I have a small comment. ScipPtr is not Send. If there is no plan on making ScipPtr Send I would do Rc<ScipPtr>, but if it is planned then Arc is fine.

@mmghannam
Copy link
Member Author

I cannot see the branch. But feel free to ping me if you make a pull request. I was asking about vars and conss because they are freed by Model. If we let scipptr free the model and the variables on the C side, we just have to be a bit careful that vars and conss are not used after free or double freed.

Sorry I forgot to push my changes :) I opened a draft PR with it #155.
Since the free method will only be called once after the last thing that has a reference in the model is freed, then use-after-free shouldn't happen. Also, because only the drop method in ScipPtr is the one responsible for freeing variables and constraints then we should be ok if we use Arc since it will only be called once.

Regarding Arc<ScipPtr>, I have a small comment. ScipPtr is not Send. If there is no plan on making ScipPtr Send I would do Rc<ScipPtr>, but if it is planned then Arc is fine.

I think I want it to be Send in the future, I just need to think what invariants need to hold for this to be safe.

@mmghannam
Copy link
Member Author

Update: First step in this was done in #155

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

No branches or pull requests

2 participants