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

Lint idea: warn about implicit drop #3915

Open
m-mueller678 opened this issue Apr 3, 2019 · 3 comments
Open

Lint idea: warn about implicit drop #3915

m-mueller678 opened this issue Apr 3, 2019 · 3 comments

Comments

@m-mueller678
Copy link

When writing low level code it is sometimes desirable to not have implicit drop calls.

For instance when interfacing with Lua one often has Rust function called by Lua, which in turn call Lua functions. One can execute a Lua function using lua_call. Errors in the Lua code are handled using longjmp, which can jump to a handler in the original Lua caller thus skipping the Execution of the rest of the Rust function.
In such a situation one wants to make sure no code is executed implicitly after lua_call (because it might be skipped).
Ideally this lint can be enabled both for single values that should not be dropped implicitly as well as functions in which nothing should be dropped implicitly

@Manishearth
Copy link
Member

Manishearth commented Apr 3, 2019 via email

@oli-obk
Copy link
Contributor

oli-obk commented Apr 3, 2019

Is that even safe? I'm thinking about a situation like below

fn foo(f: impl FnOnce()) {
    // do some setup
    catch_panic(f);
    // do some cleanup
}

and if you call this as

foo(|| {
    lua_call(...);
});

and lua_call does a longjmp, the cleanup from foo is never executed, even though execution continued. This isn't just about leaking memory and forgetting drops, this can cause actual UB.

@m-mueller678
Copy link
Author

Is that even safe? I'm thinking about a situation like below

fn foo(f: impl FnOnce()) {
    // do some setup
    catch_panic(f);
    // do some cleanup
}

and if you call this as

foo(|| {
    lua_call(...);
});

and lua_call does a longjmp, the cleanup from foo is never executed, even though execution continued. This isn't just about leaking memory and forgetting drops, this can cause actual UB.

lua_call is indeed unsafe. Rust release notes 1.24.1 has some information on a related issue and seems to imply that usage is safe as long as:

  • Lua never makes longjmp over Rust stackframes with non-copy types (I assume already dropped is fine)
  • Rust code does not unwind into Lua code

rlua seems to handle this by only using lua_pcall which catches errors. I have not looked into it, but assume this messes with Lua error handlers. Error handlers in Lua are invoked immediately after an error is thrown e. g. to collect stacktraces. I think this can be worked around somewhat, but it is a niche feature anyways.
So this approach is an acceptable workaround for this usecase.

I still think this could be a useful feature once rust-lang/rust#59024 is resolved.

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

3 participants