Skip to content
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

Socket leak in multi-thread context #1425

Closed
sanpii opened this issue Apr 14, 2021 · 4 comments
Closed

Socket leak in multi-thread context #1425

sanpii opened this issue Apr 14, 2021 · 4 comments

Comments

@sanpii
Copy link

sanpii commented Apr 14, 2021

Hello,

This code leaves sockets in UNCONN state on x86_64-unknown-linux-gnu target:

fn main() {
    for _ in 0..10 {
        std::thread::spawn(|| {
            let addr = nix::sys::socket::UnixAddr::new_abstract("lock".as_bytes()).unwrap();
            let sock = nix::sys::socket::socket(
                nix::sys::socket::AddressFamily::Unix,
                nix::sys::socket::SockType::Stream,
                nix::sys::socket::SockFlag::empty(),
                None,
            ).unwrap();

            nix::sys::socket::bind(sock, &nix::sys::socket::SockAddr::Unix(addr)).ok();
        });
    }

    loop {
    }
}
$ ls -1 /proc/$(pidof nix-bug)/fd | wc -l
13
$ ss -pl | grep $(pidof nix-bug)
u_str UNCONN 0      0                                           @lock 5787260                       * 0     users:(("nix-bug",pid=1262266,fd=3))                            
u_str UNCONN 0      0                                               * 5789618                       * 0     users:(("nix-bug",pid=1262266,fd=9))                            
u_str UNCONN 0      0                                               * 5806081                       * 0     users:(("nix-bug",pid=1262266,fd=5))                            
u_str UNCONN 0      0                                               * 5789617                       * 0     users:(("nix-bug",pid=1262266,fd=6))                            
u_str UNCONN 0      0                                               * 5787261                       * 0     users:(("nix-bug",pid=1262266,fd=8))                            
u_str UNCONN 0      0                                               * 5806082                       * 0     users:(("nix-bug",pid=1262266,fd=10))                           
u_str UNCONN 0      0                                               * 5787262                       * 0     users:(("nix-bug",pid=1262266,fd=11))                           
u_str UNCONN 0      0                                               * 5797603                       * 0     users:(("nix-bug",pid=1262266,fd=7))                            
u_str UNCONN 0      0                                               * 5797602                       * 0     users:(("nix-bug",pid=1262266,fd=4))                            
u_str UNCONN 0      0                                               * 5797604                       * 0     users:(("nix-bug",pid=1262266,fd=12))                           
@asomers
Copy link
Member

asomers commented May 30, 2021

Yes, that's right. Nix's socket method returns a RawFd, so it can't do anything fancy on drop. There's no way to fix that without breaking a lot of existing Nix consumers' code. And I don't think that Nix should even try. Nix is a low-level library. A Nix consumer can implement more ergonomic types that wrap Nix's RawFd, and do fancy things like close on drop. Do you disagree?

@sanpii
Copy link
Author

sanpii commented Jun 1, 2021

If you can’t easily fix this problem, it’s probably a good idea to document this behaviour, I spent a lot of time to understand why my cron job reach the limit of file descriptors.

@FloLo100
Copy link

FloLo100 commented Jun 2, 2021

Nix's safety guarantees do not currently extent to "correct" or "expected" behaviour on the OS side. Safety is guaranteed with regard to memory safety of the rust program itself, but not in side-effects of the OS. To find out what Nix-functions do you need to read the frequently linked OS-documentation and nothing in the documentation of bind() speaks about closing the socket. Maybe we need a better crate-level description of this than "Rust friendly bindings to the various *nix system functions."
Also note that the unsafety of RawFds is currently being discussed on rust-lang level rust-lang/rust#72175

@asomers
Copy link
Member

asomers commented Aug 9, 2021

Closing this issue. I couldn't have explained it better than FloLo100.

@asomers asomers closed this as completed Aug 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants