I don't understand what Rust does with a file handle when it goes out of scope. For example, I create a file and write several words into it:
let wd = os::getcwd().unwrap_or(Path::new("/"));
let mut file = File::create(&Path::new("daemon_log.txt"));
file.write_all(format!("DAEMON CWD: {}", wd.as_str().unwrap_or("some problems")).as_bytes());
At the point where file goes out of scope, the compiler should insert instructions to free memory. If my understanding of how blocking IO is usually implemented is correct, then, apart from releasing memory, the process should also release some lock.
What I'm worried about is that in the source for File
, I cannot find any tip for compiler to do it. This old article says that all the magic goes into implementation of the Drop
trait for File
, but it seems that it's not true for now, because I cannot find Drop
trait implementation in either std::ops.rs
nor in std::old_io::fs.rs
.
UPDATE
I checked File
s implementation of write_all
again and found that the write
method works with some descriptor (FileDesc
). I haven't found any related info about it in docs, so went to GitHub and found this. It looks like the answer to my question, but I am confused by one line in the comment:
// closing stdio file handles makes no sense, so never do it
What does this mean? I should never invoke libc::close
on my fd myself? Or they are themselves not sure how it should be implemented?
For POSIX platforms, File
is defined as struct File(FileDesc)
in mod sys::fs2
, where FileDesc
is a wrapper around file descriptor number. The destructor of FileDesc
closes the file:
impl Drop for FileDesc {
fn drop(&mut self) {
// closing stdio file handles makes no sense, so never do it. Also, note
// that errors are ignored when closing a file descriptor. The reason
// for this is that if an error occurs we don't actually know if the
// file descriptor was closed or not, and if we retried (for something
// like EINTR), we might close another valid file descriptor (opened
// after we closed ours.
if self.fd > libc::STDERR_FILENO {
let _ = unsafe { libc::close(self.fd) };
}
}
}
The implementation for Windows platform defines File
as wrapper for Handle
value, the destructor of which calls CloseHandle()
.