-
Notifications
You must be signed in to change notification settings - Fork 666
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
Closure transfer fix for sched::clone
#920
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to double box cb
? I don't understand why you can't just use a single Box
.
After looking at how |
It also appears that even at its lowest level, in order to implement the FnOnce semantics, I think it would make more sense to require the callback to be a FnOnce, but I can't see a way of doing that in stable currently. |
I'm skeptical of the |
In this case the The existing implementation of clones as you have ti will only work when the child thread does not use the Either, the box needs to be copied (which it can't) or have its ownership transferred to the child process, or forgotten and never dropped at all. The only to transfer ownership to the child process involves wrapping a the boxed closure in an additional box (I'm still not entirely clear on the why there). |
Another alternative fix that could be used here is raising that concern to the caller and using a more direct analogous type to what the syscall is actually expecting and have the wrapper take a |
I agree. But I'm not comfortable with the double-box solution without knowing why it's necessary. Did you check the history of the file in |
So, on your recommendation, I'm going back through the years of commits to https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/thread.rs and it goes back quite some way through pre-stable rust (back before I asked around on The existing code masked a fatal compile error that would have caught this using a |
I've fixed it up in a way that should disrupt the interface as little as possible using the double boxing. I've also noticed that the way the stack is passed into clone as a |
Fixes nix-rust#919 Annotate the correct lifetime (`'static`) for the closure transferred to the child process of the clone. Properly box the closure in the parent then rebox it in the child to ensure that the closure is dropped at the end of the invocation in the child rather than at the end of the call to `clone` in the parent. For some reason, unwrapping the boxed function itself caused all kinds of mayhem, so it instead ends up wrapped in an additional box from which it is then unwrapped.
This reverts commit ba0a5e6.
This test appears to be incredibly flaky and causing errors in the `sys::tests::test_sigwait` test which can't be replicated locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that explanation for double-boxing makes sense. I think it'll make even more sense when expressing things using the new dyn Trait
syntax introduced by the latest compiler.
Don't forget to add a CHANGELOG entry.
src/sched.rs
Outdated
@@ -119,3 +119,34 @@ pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> { | |||
|
|||
Errno::result(res).map(drop) | |||
} | |||
|
|||
#[cfg(not)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cfg what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to see if the tests on travis would pass if the test was disabled. It seems that with this test in place, both this test and the sys::wait::tests::test_waitpid
test would fail in various situations, but not in a way that I could replicate locally, even when building for targets that were failing in travis.
src/sched.rs
Outdated
#[test] | ||
fn simple_clone() { | ||
// Stack *must* outlive the child. | ||
let mut stack = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May as well combine these lines into let mut stack = vec![0u8; 4096]
This reverts commit e78c659.
Doesn't seem to actually work here.
246bf3b
to
cde6e3e
Compare
44e21b6
to
769d664
Compare
eb4e312
to
199f83d
Compare
Anyone still working on this? |
8518bbb
to
05657e2
Compare
Fixes #919
Annotate the correct lifetime (
'static
) for the closure transferred tothe child process of the clone.
Properly box the closure in the parent then rebox it in the child to
ensure that the closure is dropped at the end of the invocation in the
child rather than at the end of the call to
clone
in the parent.For some reason, unwrapping the boxed function itself caused all kinds
of mayhem, so it instead ends up wrapped in an additional box from which
it is then unwrapped.