ls: release directory fds before recursing to avoid EMFILE - 12x mem improv (#10894)

This commit is contained in:
Chris Dryden
2026-02-12 14:46:47 -05:00
committed by GitHub
parent caf7c44a9c
commit 57043cbb63
2 changed files with 29 additions and 1 deletions
+5
View File
@@ -2496,6 +2496,11 @@ fn enter_directory(
display_items(&entries, config, state, dired)?;
if config.recursive {
// release the open fd before recursing to not run out of resources
for entry in &entries {
entry.de.take();
}
drop(read_dir);
for e in entries
.iter()
.skip(if config.files == Files::All { 2 } else { 0 })
+24 -1
View File
@@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore (words) READMECAREFULLY birthtime doesntexist oneline somebackup lrwx somefile somegroup somehiddenbackup somehiddenfile tabsize aaaaaaaa bbbb cccc dddddddd ncccc neee naaaaa nbcdef nfffff dired subdired tmpfs mdir COLORTERM mexe bcdef mfoo timefile
// spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry awith acolons
// spell-checker:ignore (words) fakeroot setcap drwxr bcdlps mdangling mentry awith acolons NOFILE
#![allow(
clippy::similar_names,
clippy::too_many_lines,
@@ -13,6 +13,8 @@
#[cfg(all(unix, feature = "chmod"))]
use nix::unistd::{close, dup};
use regex::Regex;
#[cfg(unix)]
use rlimit::Resource;
#[cfg(not(target_os = "openbsd"))]
use std::collections::HashMap;
#[cfg(target_os = "linux")]
@@ -6992,3 +6994,24 @@ fn test_ls_proc_self_fd_no_errors() {
.succeeds()
.stderr_does_not_contain("cannot access");
}
#[test]
#[cfg(unix)]
fn test_ls_recursive_no_fd_leak() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let deep_path: String = (1..=30)
.map(|i| i.to_string())
.collect::<Vec<_>>()
.join("/");
at.mkdir_all(&deep_path);
scene
.ucmd()
.arg("-R")
.arg("1")
.limit(Resource::NOFILE, 20, 20)
.succeeds()
.stderr_is("");
}