-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Add File::try_clone #31069
Add File::try_clone #31069
Conversation
565c61d
to
7c979a5
Compare
Looks great; looking forward to removing my much more fragile platform specific code. |
7c979a5
to
a0cb1d2
Compare
This seems reasonable to me, although I will cc @rust-lang/libs and tag with it to make sure we're all good with the insta-stablilization. |
I know this can't cause memory unsafety, but isn't it very unexpected to be able to modify a file from two threads simultaneously (without additional synchronization, writing to the file will be very amusing at best) |
@oli-obk I hate to be the bearer of unexpected news, but that is already the case: @alexcrichton I implemented this at @reem's request, so he'd be able to better speak to the use cases. |
Ugh, ugly. Still, there you are at least bound to an instance. So what's the difference between |
It's pretty annoying to access the impls for |
Hmm, I actually could get by in my case with an EDIT: For clarity, the case is moving from one enum variant which contains a File to another enum variant which should contain the same File with an |
I don't know how powerful impl specialization would be, but could it create a special impl for |
@oli-obk That seems overly complicated and would be a lot of complexity when simply duplicating a file handle can be done now fairly easily with just a single public method. |
I'm aware of that. But it's much clearer that Since the borrowing semantics of |
Even if you duplicate a |
Yes, but shared ownership is represented through
It's probably not important anyway. We can always get true ownership back through a newtype that doesn't give access to the internal value. Still a sad deviation, but one that's already happened, now we gotta live with it. |
@oli-obk I at least would consider us to not perform that sort of specialization or optimization in the future. There are some use cases where you want an entirely separate handle and/or file descriptor to pass to a library which it itself calls |
insta-stabilizing seems wrong (why is this PR special)? If any time is right for it, it's this week though; it will still need 11 weeks to reach the stable release. |
Fair enough, I'm fine with landing it unstable. I'll update it tonight. |
a0cb1d2
to
c39d1ad
Compare
Updated to be unstable. |
I'm fine with this functionality, under the rubric of exposing cross-platform IO APIs that apply to our various IO objects (part of the vision of IO reform). The name isn't great, though. If you succeed here, you haven't really cloned, you've created a new alias. (And we also avoid |
@aturon note, however, that we have already stabilized |
@aturon To bikeshed a bit more, |
Yeah, I thought about that, though I'd argue it's mildly more obvious what's going on in those cases. D'oh! I'm surprised that got through, though I imagine I signed off on it at some point :-) Given the |
Agreed that |
The libs team discussed this during triage today and the conclusion was to merge (mirrors existing APIs, seems like good functionality to have). @sfackler could you open a tracking issue and update the pointer here? Other than that r=me |
c39d1ad
to
a414b61
Compare
@bors r=alexcrichton |
📌 Commit a414b61 has been approved by |
I have it set as stable right now under the rationale that it's extending an existing, stable API to another type in the "obvious" way. r? @alexcrichton cc @reem
@@ -338,6 +338,12 @@ impl File { | |||
Ok(newpos as u64) | |||
} | |||
|
|||
pub fn duplicate(&self) -> io::Result<File> { | |||
Ok(File { | |||
handle: try!(self.handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)), |
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.
Asking 3.5 years after the fact: Does anyone know why we set inheritable = true
here? I've run into a bug (because duct
was abusing File::try_clone
somewhat) where pipes get inherited by processes that aren't supposed to inherit them, when spawning happens on multiple threads at once. Normally the CREATE_PROCESS_LOCK
prevents this, but this line here creates inheritable handles outside of that lock. duct
is going to work around this by making all the appropriate system calls explicitly. But this inheritable flag might be cause some programs in the wild to keep files open longer than they should (even without a multi-threaded race condition like mine), and on Windows in particular that could cause bugs by making them un-deletable.
File handles shouldn't be inheritable in general. `std::process::Command` takes care of making them inheritable when child processes are spawned, and the `CREATE_PROCESS_LOCK` protects against races in that section on Windows. But `File::try_clone` has been creating inheritable file descriptors outside of that lock, which could be leaking into other child processes unintentionally. See also rust-lang#31069 (comment).
…ichton make File::try_clone produce non-inheritable handles on Windows ~**NOT READY FOR REVIEW.** This PR is currently mainly to trigger CI so that I can see what happens. (Is there a better way to trigger CI?) I don't know whether this change makes sense yet.~ (Edit: @Mark-Simulacrum clarified that CI doesn't currently run on Windows.) --- File handles shouldn't be inheritable in general. `std::process::Command` takes care of making them inheritable when child processes are spawned, and the `CREATE_PROCESS_LOCK` protects against races in that section on Windows. But `File::try_clone` has been creating inheritable file descriptors outside of that lock, which could be leaking into other child processes unintentionally. See also rust-lang#31069 (comment).
…ichton make File::try_clone produce non-inheritable handles on Windows ~**NOT READY FOR REVIEW.** This PR is currently mainly to trigger CI so that I can see what happens. (Is there a better way to trigger CI?) I don't know whether this change makes sense yet.~ (Edit: @Mark-Simulacrum clarified that CI doesn't currently run on Windows.) --- File handles shouldn't be inheritable in general. `std::process::Command` takes care of making them inheritable when child processes are spawned, and the `CREATE_PROCESS_LOCK` protects against races in that section on Windows. But `File::try_clone` has been creating inheritable file descriptors outside of that lock, which could be leaking into other child processes unintentionally. See also rust-lang#31069 (comment).
I have it set as stable right now under the rationale that it's extending an existing, stable API to another type in the "obvious" way.
r? @alexcrichton
cc @reem