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

Be resilient to most IO error and filesystem loop while walking dirs #10214

Merged
merged 3 commits into from
Jan 5, 2022

Conversation

weihanglo
Copy link
Member

@weihanglo weihanglo commented Dec 18, 2021

Let PathSource::walk be resilient to most IO errors and filesystem loop.

This PR also

Fixes #10213.

@rust-highfive
Copy link

r? @ehuss

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 18, 2021
@alexcrichton
Copy link
Member

Is there a way we could detect and filter these cases from walkdir, such as ignoring broken symlinks entirely?

@weihanglo
Copy link
Member Author

Indeed we can recover from broken symlink and some IO errors. For filesystem loop, I guess we can simply emit a warning inside fn walk and skip the entry? At least user stuck in root can be informed that a lot filesystem loops happened.

The code snippet need to change as below:

        for entry in walkdir {
            match entry {
                Ok(entry) => {
                    if !entry.file_type().is_dir() {
                        ret.push(entry.into_path());
                    }
                },
                Err(e) => {
                    if e.loop_ancestor().is_some() {
                        // emit some warning!!!!!
                        continue
                    }
                    if let Some(path) = e.path() {
                        ret.push(path.to_path_buf());
                    }
                }
            }
        }

@alexcrichton
Copy link
Member

If a loop is as common as node_modules installations we probably don't want to warn about it but otherwise handling it somewhat gracefully seems reasonable.

@weihanglo weihanglo changed the title Revert "Detect filesystem loop during walking the projects" Be resilient to most IO error and filesystem loop while walking dirs Dec 21, 2021
@weihanglo
Copy link
Member Author

From my own experience, a normal Node.js project should not have any nested node_modules in its dependencies, so the warning might be rare. I'm ok to remove the warning though if so, #9528 needs a reopen.

(_, Some(err)) if err.kind() == PermissionDenied => {
return Err(Error::new(PermissionDenied, err.to_string()).into());
}
(Some(path), _) => ret.push(path.to_path_buf()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, what's going on here? This looks like it's ignoring all errors that are not permission denied?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If cargo doesn't handle permission error intentionally, this EACCES test case might pass silently. The old behavior before adopting walkdir returns errors from fs::read_dir calls directly, as well as it just unwraps DirEntry without handling Result.

let mut entries: Vec<PathBuf> = fs::read_dir(path)
.with_context(|| format!("cannot read {:?}", path))?
.map(|e| e.unwrap().path())
.collect();

With walkdir, cargo cannot tell whether the error is permission error or a broken link. Generally, walkdir emits three kinds of errors:

  1. Symlink loop errors: Cargo already takes care of it and shows a warning in this PR.
  2. IO errors with a path: I guess cargo can recover from the path, and later let the caller decide to ignore it or if the caller does access the path and hits the error.
  3. IO errros without a path: Cargo can simply propagate it to callers. This is rare because walkdir only emits this kind for either opening the file to check symlink loop or handling the Result<DirEntry> generated from read_dir().

I've updated this PR to reflect aforementioned change. There is an enhancement can do such as emitting warnings for those recoverable errors, but I doubt its usefulness.

@alexcrichton
Copy link
Member

Ah ok if we don't expect this to be common then a warning seems fine and we can adjust later if necessary.

Recover from IO errors wile walking directories, only abort when error
from `walkdir` is without an path to recover.
Remove `build_script::build_script_scan_eacces`  test case because cargo
ignores it and returns its path during a `cargo build`. The caller still
has a chance to hit the IO error if they does access it.
@alexcrichton
Copy link
Member

@bors: r+

Ok sounds good to me!

@bors
Copy link
Contributor

bors commented Jan 5, 2022

📌 Commit d92dcea has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 5, 2022
@bors
Copy link
Contributor

bors commented Jan 5, 2022

⌛ Testing commit d92dcea with merge 2478331...

@bors
Copy link
Contributor

bors commented Jan 5, 2022

☀️ Test successful - checks-actions
Approved by: alexcrichton
Pushing 2478331 to master...

@bors bors merged commit 2478331 into rust-lang:master Jan 5, 2022
@weihanglo weihanglo deleted the revert-10188-issue-9528 branch January 7, 2022 10:27
@weihanglo
Copy link
Member Author

Should this fix be included in next beta? I feel like it should or we need to backport it after 1.59-beta released.

@alexcrichton
Copy link
Member

Yeah that seems reasonable to me, would you be up for preparing the PR?

weihanglo pushed a commit to weihanglo/cargo that referenced this pull request Jan 12, 2022
…alexcrichton

Be resilient to most IO error and filesystem loop while walking dirs

Let `PathSource::walk` be resilient to most IO errors and filesystem loop.

This PR also

- Add a test validating the resilience against filesystem loop to prevent regression.
- Emit warning when filesystem loop found while walking the filesystem. This is the only way I can think of now to solve rust-lang#9528

Fixes rust-lang#10213.
bors added a commit that referenced this pull request Jan 12, 2022
[Beta] backport "Be resilient to most IO error and filesystem loop while walking dirs"

Beta backport of #10214.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 12, 2022
Update cargo

6 commits in 358e79fe56fe374649275ca7aebaafd57ade0e8d..06b9d31743210b788b130c8a484c2838afa6fc27
2022-01-04 18:39:45 +0000 to 2022-01-11 23:47:29 +0000
- Port cargo to clap3 (rust-lang/cargo#10265)
- feat: support rustflags per profile (rust-lang/cargo#10217)
- Make bors ignore the PR template so it doesn't end up in merge messages (rust-lang/cargo#10267)
- Be resilient to most IO error and filesystem loop while walking dirs (rust-lang/cargo#10214)
- Remove the option to disable pipelining (rust-lang/cargo#10258)
- Always ask rustc for messages about artifacts, and always process them (rust-lang/cargo#10255)
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 13, 2022
Update cargo

6 commits in 358e79fe56fe374649275ca7aebaafd57ade0e8d..06b9d31743210b788b130c8a484c2838afa6fc27
2022-01-04 18:39:45 +0000 to 2022-01-11 23:47:29 +0000
- Port cargo to clap3 (rust-lang/cargo#10265)
- feat: support rustflags per profile (rust-lang/cargo#10217)
- Make bors ignore the PR template so it doesn't end up in merge messages (rust-lang/cargo#10267)
- Be resilient to most IO error and filesystem loop while walking dirs (rust-lang/cargo#10214)
- Remove the option to disable pipelining (rust-lang/cargo#10258)
- Always ask rustc for messages about artifacts, and always process them (rust-lang/cargo#10255)
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 13, 2022
Update cargo

6 commits in 358e79fe56fe374649275ca7aebaafd57ade0e8d..06b9d31743210b788b130c8a484c2838afa6fc27
2022-01-04 18:39:45 +0000 to 2022-01-11 23:47:29 +0000
- Port cargo to clap3 (rust-lang/cargo#10265)
- feat: support rustflags per profile (rust-lang/cargo#10217)
- Make bors ignore the PR template so it doesn't end up in merge messages (rust-lang/cargo#10267)
- Be resilient to most IO error and filesystem loop while walking dirs (rust-lang/cargo#10214)
- Remove the option to disable pipelining (rust-lang/cargo#10258)
- Always ask rustc for messages about artifacts, and always process them (rust-lang/cargo#10255)
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 19, 2022
Update cargo

16 commits in 358e79fe56fe374649275ca7aebaafd57ade0e8d..95bb3c92bf516017e812e7f1c14c2dea3845b30e
2022-01-04 18:39:45 +0000 to 2022-01-18 17:39:35 +0000
- Error when setting crate type of both dylib and cdylib in library (rust-lang/cargo#10243)
- Include `help` in `--list` (rust-lang/cargo#10300)
- Add report subcommand to bash completion. (rust-lang/cargo#10295)
- Downgrade some log messages. (rust-lang/cargo#10296)
- Enable shortcut for triage bot (rust-lang/cargo#10298)
- Bump to 0.61.0, update changelog (rust-lang/cargo#10294)
- use new cargo fmt option (rust-lang/cargo#10291)
- Add `run-fail` to semver-check for docs (rust-lang/cargo#10287)
- Use `is_symlink()` method (rust-lang/cargo#10290)
- Stabilize namespaced and weak dependency features. (rust-lang/cargo#10269)
- Port cargo to clap3 (rust-lang/cargo#10265)
- feat: support rustflags per profile (rust-lang/cargo#10217)
- Make bors ignore the PR template so it doesn't end up in merge messages (rust-lang/cargo#10267)
- Be resilient to most IO error and filesystem loop while walking dirs (rust-lang/cargo#10214)
- Remove the option to disable pipelining (rust-lang/cargo#10258)
- Always ask rustc for messages about artifacts, and always process them (rust-lang/cargo#10255)
@ehuss ehuss added this to the 1.59.0 milestone Feb 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"File system loop found" upon cargo build
5 participants