Uh oh!
There was an error while loading. Please reload this page.
Provide a way of obtaining numeric file descriptors. - #15643
Provide a way of obtaining numeric file descriptors.#15643errordeveloper wants to merge 2 commits into
Conversation
errordeveloper
commented
Jul 13, 2014
it is still missing Windows support... and unit tests. Would be great to hear some feedback before I proceed with more work on this. |
errordeveloper
commented
Jul 13, 2014
My main question regarding the unit tests is whether I should add it to every implementation of this trait except from the trait definition, right? |
errordeveloper
commented
Jul 13, 2014
Regarding Windows, I have no idea, so please do feel free to make some suggestions... Does it even have FDs in the same sense? |
alexcrichton
commented
Jul 13, 2014
I'm a little wary to do this because of, sadly, windows. I don't quite grok how windows deals with I would want to understand better how this works with windows before moving forward, personally. |
errordeveloper
commented
Jul 13, 2014
@alexcrichton understood.
I have briefly though of doing something along the lines of: fnwith_c_fd(&self,close_after:bool, block: |libc::c_int| -> IoResult){matchblock(self.fd()){ ...}}Although this seems rather useful and makes sense along the side of To me, the most disapointing bit was finding out that there is |
errordeveloper
commented
Jul 13, 2014
@alexcrichton by looking at There is only an additional method: pubfnfd(&self) -> fd_t{self.inner.fd}pubfnhandle(&self) -> libc::HANDLE{unsafe{ libc::get_osfhandle(self.fd())as libc::HANDLE}}So I guess I could provide We need to check with |
alexcrichton
commented
Jul 13, 2014
I'm not sure whether a file descriptor is a first-class thing in windows or what relation it has to HANDLE other than there's likely a one-to-one mapping. Most windows apis deal with a HANDLE instead of a file descriptor, so this change would definitely be favoring unix over windows. From your example above, however, this is why I've been hesitant to add it in the past. Many methods on these objects won't work if you start manually fiddling with flags on the file descriptor itself. |
retep998
commented
Jul 13, 2014
Perhaps |
errordeveloper
commented
Jul 13, 2014
I have considered this and it's in the doc comment. There is not much you
|
alexcrichton
commented
Jul 13, 2014
This is not necessarily a security bug, it has the possibility of becoming a memory safety bug. Functions in libnative (and possibly libuv as well) may be designed assuming complete control of a file descriptor. If this control is broken, the broken assumptions may lead to memory unsafety. I don't think we have any examples of this today, but that doesn't mean that it's impossible to have. |
errordeveloper
commented
Jul 13, 2014
OK, sure. I'm not completely opposing making it an unsafe function. And, So best solution would probably be to just simply call those functions
|
andrew-d
commented
Jul 13, 2014
For what it's worth, a |
errordeveloper
commented
Jul 13, 2014
So my Stack Overflow post resulted in a solution that will work for what I am doing right now. |
errordeveloper
commented
Jul 13, 2014
I do still insist on this going forward. @alexcrichton you commented earlier:
So it does occur to me now, based on the solution posted on Stack Overflow, that Perhaps In fact, one might actually simply use this to could how many files they have opened so far. As far as standard run time goes, it could actually attempt to protect form file descriptor leaks by preventing someone from opening the same file over and over again with the same mode... It would just tell you, that this had already been open and here is the original handle. |
alexcrichton
commented
Jul 14, 2014
The librustuv and libnative interfaces are likely to always be experimental and not intended for general consumption. They provide their own access to file descriptors out of necessity for the library itself, I wouldn't recommend relying on the native/rustuv interfaces for extracting file descriptors. If we were to add this function, I believe that it should be Also, from what @andrew-d said about file descriptors on windows, this would be tying rust permanently to their C runtime library. I'm not entirely sure if that's desirable or not? |
errordeveloper
commented
Jul 15, 2014
Another use case for this would when one wants to use Anyhow, right now I need to use externcrate std;externcrate native;externcrate debug;use native::io::file::open;use std::rt::rtio::{Open,Read};use std::os::{MemoryMap,MapReadable,MapWritable,MapFd};fnmain(){let path = "test.bin";let file =
matchopen(&path.to_c_str(),Open,Read){Err(_) => {fail!("Something is terribly wrong!");},Ok(f) => { f },};let fmap = matchMemoryMap::new(4096u,[MapReadable,MapWritable,MapFd(file.fd())]){Err(_) => {fail!("Something is terribly wrong!");},Ok(f) => { f },};println!("{:?}", fmap);} |
alexcrichton
commented
Jul 15, 2014
Ok, after stewing for a bit I think I'd like to move forward with this. @errordeveloper, could you add the following pieces to the pr?
And some unresolved questions I also have:
Does that sounds ok? We can deal with the questions in time, and I'm around to help out with any questions you have, feel free to reach out on IRC! (I'm acrichto) |
huonw
commented
Jul 15, 2014
|
chris-morgan
commented
Jul 18, 2014
I do not like this, Sam-I-Am. Supposing I wish to use a different runtime that doesn’t use that sort of descriptor at all—a bare metal case might do it, or perhaps an emscripten-specific runtime for running in the browser (I can easily imagine that one having absolutely nothing to do with such magic numbers). I do not believe it is at all reasonable to expect to be able to have such a descriptor, at the language level at least. Still, for pragmatism’s sake, it must evidently be exposed somewhere. Given that, I would say very strongly that such functions should be marked unsafe, and probably unstable also. I would think also that having it on a separate trait would be a good thing—could the trait even live in the libc crate to make it absolutely clear that it’s That Sort of Thing? |
chris-morgan
commented
Jul 18, 2014
A benefit of using a trait for this is that you could then use it as a generic bound, e.g. for exposing a safe interface over |
errordeveloper
commented
Jul 18, 2014
I cannot disagree with you, Chris. I do however believe that current
|
huonw
commented
Jul 18, 2014
A trait is useless for distiguishing things that only have sensible implementation under certain runtimes, the |
This is to improve the interoperability with external C libraries. One should be able to leverage most Rust's standard run-time functions for openning and closing files with all the error handling etc, while only making C library calls when it's very neccessary.
errordeveloper
commented
Jul 20, 2014
@huonw what do you say: add |
errordeveloper
commented
Jul 30, 2014
I have just notice new rust-lang/rfcs#185... If that's to be implemented, I'd hold on with the |
tbu-
commented
Aug 13, 2014
I don't see why getting the file descriptor should be unsafe – getting a raw pointer from a As per the Rust design documents, reading private values from objects isn't considered unsafe if I remember correctly. |
l0kod
commented
Aug 18, 2014
First, about the Second, it would be safer to enclose the file descriptor use into a closure. What's unsafe about file descriptor is their lifetime: they can be closed by another piece of code, refer to a different file (i.e. I don't think we need a We could use a I used The problem is that we get |
l0kod
commented
Aug 18, 2014
Not the right choice, prefer to return To properly handle file descriptor lifetime in bindings, the right thing to do is to wrap the bindings in a Rust object who handle the file descriptor closing. |
tbu-
commented
Aug 19, 2014
I don't see how reading the file descriptor is unsafe in any way – only using them to construct other things should be unsafe. Compare (which is safe) to (which is unsafe). Getting the raw value of a pointer is not unsafe at all, while actually using it is. This is how it should be handled with file descriptors IMO, getting them out of a structure is no problem at al – only using them to construct other things should be unsafe. |
tbu-
commented
Aug 26, 2014
What are file descriptors supposed to be on Windows? I only know of |
thestinger
commented
Aug 26, 2014
It has numeric file descriptors in the C runtime, which can be converted to and from a |
thestinger
commented
Aug 26, 2014
Anyway, it would be nice to expose a proper pubstructFileDesc{fd:c_int}implFileDesc{pubunsafefnfrom_handle(fd:c_int) -> FileDesc{ ...}pubfnas_handle(&self) -> c_int{ ...}pubfninto_handle(self) -> c_int{ ...}pubfndup(&self) -> Result<FileDesc,Error>{ ...}pubfnread(&self,buffer:&mut[u8]) -> IoResult<uint>{ ...}pubfnwrite(&self,buffer:&[u8]) -> IoResult<uint>{ ...}
...
}An important thing to keep in mind is that all files should be atomically |
l0kod
commented
Aug 26, 2014
Preferable to use a dedicated
Like I said previously, we should probably take care of file descriptor type (e.g. regular file, socket, directory) and their capabilities: it should not be possible to attempt a To avoid this, traitBasicFileDesc{pubunsafefnfrom_handle(fd:fd_t) -> Self{ … }// …pubfndup(&self) -> IoResult<Self>{ … fcntl() … }// also called by clone()?}implBasicFileDescforRegularFd;// same for all other file descriptor types…traitDirFileDesc{pubfnopenat(…) -> IoResult<FileDesc>// enum defined belowpubfngetdents(…) -> IoResult<DirEntry>// or readdir-like// …}implDirFileDescforDirectoryFd;traitRwFileDesc{pubfnread(…) -> IoResult<uint>{ ...}// …}implRwFileDescforRegularFd;implRwFileDescforCharDevFd;// …traitDevFileDesc{fnioctl(…) -> IoResult<()>// …}implDevFileDescforCharDevFd;implCharDevFd{fnisatty(…) -> bool{ … }}enumFileDesc{Regular(RegularFd),Directory(DirectoryFd),// implement openat, linkat…CharDev(CharDevFd),// implement ioctl, isatty…BlockDev(BlockDevFd),// implement ioctl…Pipe(PipeFd),Symlink(SymlinkFd),Socket(SocketFd),Unknown(UnknownFd),// seems to be possible: bad thing for static typing but could implement all traits}E.g. the
Right, |
thestinger
commented
Aug 26, 2014
@l0kod: |
thestinger
commented
Aug 26, 2014
If you do this with an |
tbu-
commented
Aug 26, 2014
Indeed, the whole point we wanted to achieve with this was compatiblity with low-level libraries in other languages – so wrapping it up as such an enum would have the wrong effect in my opinion. |
l0kod
commented
Aug 26, 2014
OK, I missed some file descriptor types ;) but It's probably why |
l0kod
commented
Aug 26, 2014
Doesn't it one of the goal of static typing: to avoid confusion between different things? I don't see why it would be a problem for binding with low-level library. |
tbu-
commented
Aug 26, 2014
Because C doesn't understand these enums, it only "understands" the raw |
l0kod
commented
Aug 26, 2014
Yes, C understand the raw |
thestinger
commented
Aug 26, 2014
By adding abstraction and typing restrictions, it's no longer a low-level library and can no longer express everything that you can in C. Exposing low-level functionality does not preclude having high-level abstractions built on top of them. It shouldn't go beyond what is necessary to achieve safety unless it's not making any use cases more difficult. |
l0kod
commented
Aug 26, 2014
Yes, that's the goal of proper wrapping, to avoid errors :) I don't see the difference of use between a single The idea is that bindings who return file descriptors (e.g. |
petrochenkov
commented
Aug 27, 2014
Plus to thestinger, I feel the primary goal is a possibility to use an operating system API in its entirety. |
l0kod
commented
Aug 28, 2014
Good news! libuv now support file descriptors: joyent/libuv#1435. |
retep998
commented
Aug 28, 2014
Of particular note is that libuv provides |
alexcrichton
commented
Sep 8, 2014
Closing due to inactivity. There are many changes planned to the I/O libraries, especially libnative. While these changes settle down over the coming weeks, something like this will definitely be included. I would recommend holding off to see how the new design of libnative works out. The plan is to have high-level primitives in libstd which provide access to lower-level primitives in libnative which in turn provide access to the raw file descriptor/handle objects. |
errordeveloper
commented
Sep 9, 2014
@alexcrichton I am definitely looking forward to see those changes. Is there a tracking issues for it? |
alexcrichton
commented
Sep 9, 2014
I'd follow rust-lang/rfcs#219 which, although closed, will be updated with the next course of action. |
aturon
commented
Sep 9, 2014
See (and please comment on!) this new RFC. |
l0kod
commented
Nov 9, 2014
Merged RFC: https://github.com/rust-lang/rfcs/blob/master/text/0230-remove-runtime.md Related issue: #17325. |
l0kod
commented
Nov 22, 2014
New PR: #19169 |
This is to improve the interoperability with external C libraries.
One should be able to leverage most Rust's standard run-time functions
for openning and closing files with all the error handling etc, while
only making C library calls when it's very neccessary.