Repository: sharkdp/fd (language: rust)

Issue:
Error after successful return (bug not located): "Unwrap error", after printing `-1`'s result
**Describe the bug you encountered:**
Query returns or reports and error after normal, successful usage.

**Describe what you expected to happen:**
Print result of `fd -d 3 -1 cheat.sheets .` and exit.

Does not error on `fd -d 3 -1 cheat.sheets`, without final `.` search path arg.

**What version of `fd` are you using?**
`fd 8.1.1`
**Which operating system / distribution are you on?**
`Darwin 18.7.0 x86_64`

```
^C^C
$ env RUST_BACKTRACE=1 fd -d 3 -1 cheat.sheets .
hosting/Reference/cheat.sheets
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "SendError(..)"', src/walk.rs:371:21
stack backtrace:
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "SendError(..)"', src/walk.rs:371:21
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: "SendError(..)"', src/walk.rs:371:21
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::rust_panic_with_hook
   5: rust_begin_unwind
   6: core::panicking::panic_fmt
   7: core::result::unwrap_failed
   8: fd::walk::spawn_senders::{{closure}}::{{closure}}
   9: <ignore::walk::FnVisitorImp as ignore::walk::ParallelVisitor>::visit
  10: ignore::walk::Worker::run_one
  11: crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::rust_panic_with_hook
   5: rust_begin_unwind
   6: core::panicking::panic_fmt
   7: core::result::unwrap_failed
   8: fd::walk::spawn_senders::{{closure}}::{{closure}}
   9: <ignore::walk::FnVisitorImp as ignore::walk::ParallelVisitor>::visit
  10: ignore::walk::Worker::run_one
  11: crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Any', /Users/brew/Library/Caches/Homebrew/cargo_cache/registry/src/github.com-1ecc6
299db9ec823/ignore-0.4.15/src/walk.rsstack backtrace:
:1294:17
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::rust_panic_with_hook
   5: rust_begin_unwind
   6: core::panicking::panic_fmt
   7: core::result::unwrap_failed
   8: fd::walk::spawn_senders::{{closure}}::{{closure}}
   9: <ignore::walk::FnVisitorImp as ignore::walk::ParallelVisitor>::visit
  10: ignore::walk::Worker::run_one
  11: crossbeam_utils::thread::ScopedThreadBuilder::spawn::{{closure}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
   1: core::fmt::write
   2: std::io::Write::write_fmt
   3: std::panicking::default_hook::{{closure}}
   4: std::panicking::rust_panic_with_hook
   5: rust_begin_unwind
   6: core::panicking::panic_fmt
   7: core::result::unwrap_failed
   8: ignore::walk::WalkParallel::visit
   9: fd::walk::scan
  10: fd::run
  11: fd::main
  12: std::rt::lang_start::{{closure}}
  13: main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```


Discussion / hints:
Uhh. Regarding ` /Users/brew/Library/Caches/Homebrew/cargo_cache/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.15/src/walk.rs`...`stack backtrace:`...``:1294:17`

I don't even have ignore-0.4.15 in the cargo sources. I think this is probably a packaging bug, *brew*.

```
λ ~ fd walk.rs .cargo
.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.10/examples/walk.rs
.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.10/src/walk.rs
.cargo/registry/src/github.com-1ecc6299db9ec823/git2-0.13.8/src/revwalk.rs
.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.14/src/walk.rs
.cargo/registry/src/github.com-1ecc6299db9ec823/ignore-0.4.14/examples/walk.rs
```



Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 605e280e5..4eaf010cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
 
 ## Bugfixes
 
+- Avoid panic when performing limited searches in directories with restricted permissions, see #678
 - Invalid numeric command-line arguments are silently ignored, see #675
 - Disable jemalloc on Android, see #662
 
diff --git a/src/walk.rs b/src/walk.rs
index 1061d66c1..456b717d6 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -358,19 +358,27 @@ fn spawn_senders(
                         DirEntry::BrokenSymlink(path)
                     }
                     _ => {
-                        tx_thread
-                            .send(WorkerResult::Error(ignore::Error::WithPath {
-                                path,
-                                err: inner_err,
-                            }))
-                            .unwrap();
+                        match tx_thread.send(WorkerResult::Error(ignore::Error::WithPath {
+                            path,
+                            err: inner_err,
+                        })) {
+                            Ok(_) => {
+                                return ignore::WalkState::Continue;
+                            }
+                            Err(_) => {
+                                return ignore::WalkState::Quit;
+                            }
+                        }
+                    }
+                },
+                Err(err) => match tx_thread.send(WorkerResult::Error(err)) {
+                    Ok(_) => {
                         return ignore::WalkState::Continue;
                     }
+                    Err(_) => {
+                        return ignore::WalkState::Quit;
+                    }
                 },
-                Err(err) => {
-                    tx_thread.send(WorkerResult::Error(err)).unwrap();
-                    return ignore::WalkState::Continue;
-                }
             };
 
             if let Some(min_depth) = config.min_depth {


Test patch: