Skip to content

Command::output panics on Linux if more than 1024 file descriptors are open #40894

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

Closed
matklad opened this issue Mar 29, 2017 · 5 comments
Closed
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@matklad
Copy link
Member

matklad commented Mar 29, 2017

Issue originally reported by @knsd.

Command::open uses select on Linux:

libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(),
to read from both stderr and stdout. This won't always work, because select is limited to file descriptors less than FD_SETSIZE (1024).

Thus, if you raise ulimit -n to more than 1024, the following code panics

use std::fs::File;
use std::process::Command;

const FD_SETSIZE: usize = 1024;
const STDIO: usize = 3;
const EXE: &'static str = "/usr/bin/env";

fn main() {
    let mut files = Vec::new();

    for _ in 0..FD_SETSIZE - STDIO * 2 {
        let file = File::open(&EXE).unwrap();
        files.push(file)
    }

    let output = Command::new(EXE).output();
    println!("{:?}", output)
}
thread 'main' panicked at 'index out of bounds: the len is 16 but the index is 16', /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/slice.rs:664
@matklad matklad changed the title Command::output panics on Linux if more then 1024 file descriptors are open Command::output panics on Linux if more than 1024 file descriptors are open Mar 29, 2017
@alexcrichton
Copy link
Member

Wow.

Times like this are when I'm super glad we use rust, otherwise this'd be a super weird segfault!

We should probably just do epoll/kqueue and/or fall back to spawning threads when this happens.

@alexcrichton alexcrichton added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Mar 30, 2017
@alexcrichton
Copy link
Member

@matklad out of curiosity how'd you discover this?

@Stebalien
Copy link
Contributor

You could also just use poll for maximum compatibility.

@matklad
Copy link
Member Author

matklad commented Mar 30, 2017

@matklad out of curiosity how'd you discover this?

It's better to ask @knsd :)

You could also just use poll for maximum compatibility.

Looks like poll does not always work on mac: https://daniel.haxx.se/blog/2016/10/11/poll-on-mac-10-12-is-broken/. Perhaps it does not matter in this simple case of two file descriptors without timeouts.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Apr 4, 2017
This gives us the benefit of supporting file descriptors over the limit that
select supports, which...

Closes rust-lang#40894
bors added a commit that referenced this issue Apr 6, 2017
std: Use `poll` instead of `select`

This gives us the benefit of supporting file descriptors over the limit that
select supports, which...

Closes #40894
@internetionals
Copy link

Under Linux this could have also been solved by allocating a dynamic bitmap as fdset. That way you can easily watch hundreds of thousands of filedescriptors using plain 'select'.

Note that watching fdsets with filedescriptors higher than 8192 or so would see increasing runtime overhead, as the kernel has to scan the bitmap for possible fds to watch on each call to select.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants