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

Re-entry problem #611

Closed
wants to merge 2 commits into from
Closed

Re-entry problem #611

wants to merge 2 commits into from

Conversation

surma
Copy link
Collaborator

@surma surma commented Feb 29, 2024

This PR adds a test to show crashing behavior. I have a solution ready, but wanted to discuss options first.

The Problem

new_callback (and by extension wrap_callback) take a closure, whose state has to be stored somewhere. Currently, it’s stored in a RefCell that is leaked via Box::leak. However, the closure is FnMut, which means the closure’s state needs to be mutated. RefCell::borrow_mut allows this to work by deferring the borrow checks to runtime.

However, in a re-entrant scenario (closure is invoked from JS, closure calls back in to JS and JS calls back into the same closure), the runtime borrow checker of RefCell will panic. This is, in my opinion, unexpected.

Solution

The solution I have tested is to change the closure from FnMut to Fn. That way, we can ditch the RefCell and just use Box::leak to get a *'static const F. If a developer wants to mutate state, they can still resort to RefCell or Mutex or similar mechanisms to do so.

If we change the existing APIs, it is arguably a breaking change. Adding new APIs that use Fn instead of FnMut seems clunky but allows backwards compatibility.

Open to other suggestions.

@saulecabrera
Copy link
Member

This is unfortunately one of the most fragile pieces of the bindings. It's also a bit unfortunate that currently we require leaking and 'static lifetime; I attempted to fix some of this by trying to attach the lifetime of the callback to the context. That approach is probably the one I'd suggest we go after here, but it's definitely more involved than your suggestion.

I think that breaking changes are fine, especially if it means fixing issues like this one; in that sense, in the spirit of prioritizing correctness first, I agree that your approach is probably the best to fix the issue here. Do you mind pushing your fix?

@surma
Copy link
Collaborator Author

surma commented Feb 29, 2024

@saulecabrera pushed!

@jeffcharles
Copy link
Collaborator

Please don't forget to update the CHANGELOG file and crate version before merging

@surma
Copy link
Collaborator Author

surma commented Feb 29, 2024

What version should we do? v4 for breaking change? Or is this small enough to warrant a 3.1.0-alpha.2?

@jeffcharles
Copy link
Collaborator

Yeah 4.0.0-alpha.1

@saulecabrera saulecabrera mentioned this pull request Mar 19, 2024
5 tasks
@saulecabrera
Copy link
Member

Now that #618 has landed, I believe we no longer have this issue, I'll go ahead and close this PR.

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.

3 participants