ringbahn / ringbahn

safe bindings to io-uring

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fd leak in File

Nugine opened this issue · comments

ringbahn/src/fs.rs

Lines 310 to 318 in 08e6464

impl<D: Drive> Drop for File<D> {
fn drop(&mut self) {
match self.active {
Op::Closed => { }
Op::Nothing => unsafe { libc::close(self.fd); },
_ => self.cancel(),
}
}
}

Line 315 leaks the fd.

The code below can prove that the fd is leaked.

#![forbid(unsafe_code)]

use std::os::unix::io::AsRawFd;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::thread;
use std::time::Duration;

use futures::io::AsyncReadExt;
use futures::ready;
use futures::Future;

use ringbahn::fs::File;

struct PollOnce<F>(Option<F>); // A strange future

impl<F> PollOnce<F>
where
    F: Future + Unpin,
{
    fn new(f: F) -> Self {
        Self(Some(f))
    }
}

impl<F> Future for PollOnce<F>
where
    F: Future + Unpin,
{
    type Output = Option<F::Output>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match self.0.take() {
            Some(ref mut f) => Poll::Ready(Some(ready!(Pin::new(f).poll(cx)))),
            None => Poll::Ready(None),
        }
    }
}

fn main() {
    futures::executor::block_on(async move {
        let raw_fd;

        {
            let input_file = std::fs::File::open("props.txt").unwrap();
            raw_fd = input_file.as_raw_fd();

            // ---------
            let mut input_file: File = input_file.into();
            let mut buf = vec![0; 1024];
            PollOnce::new(input_file.read(&mut buf)).await;
            // ---------

            drop(input_file);
        }
        thread::sleep(Duration::from_secs(1));
        {
            let path = std::fs::read_link(format!("/proc/self/fd/{}", raw_fd)).unwrap();
            dbg!(path);
        }
    });
}

This should have been fixed by #72