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

Panic when pipe breaks on standard output #52

Closed
delucks opened this issue Jun 21, 2019 · 1 comment
Closed

Panic when pipe breaks on standard output #52

delucks opened this issue Jun 21, 2019 · 1 comment

Comments

@delucks
Copy link

delucks commented Jun 21, 2019

Hey thanks for making such a neat tool! While using it today I discovered that the SIGPIPE signal being passed back from CLI tools that only consume a certain amount of stdout results in a panic. Here's a minimal repro of the bug:

$ RUST_BACKTRACE=1 fselect path, size from /usr | head
/usr/sbin       12288
/usr/sbin/cupsaddsmb    14328
/usr/sbin/pppoe-discovery       22528
/usr/sbin/exim_lock     18424
/usr/sbin/update-passwd 31136
/usr/sbin/genccode      10608
/usr/sbin/netscsid      118688
/usr/sbin/split-logfile 2415
/usr/sbin/cache_dump    11
/usr/sbin/cpgr  4
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', src/libstd/io/stdio.rs:690:9
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:70
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:58
             at src/libstd/panicking.rs:200
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:215
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:478
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:385
   6: std::panicking::begin_panic_fmt
             at src/libstd/panicking.rs:340
   7: std::io::stdio::_print
             at src/libstd/io/stdio.rs:690
             at src/libstd/io/stdio.rs:699
   8: fselect::searcher::Searcher::check_file
   9: fselect::searcher::Searcher::visit_dir
  10: fselect::searcher::Searcher::visit_dir
  11: fselect::searcher::Searcher::list_search_results
  12: fselect::main
  13: std::rt::lang_start::{{closure}}
  14: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:297
  15: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:92
  16: std::rt::lang_start_internal
             at src/libstd/panicking.rs:276
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  17: main
  18: __libc_start_main
  19: _start

Of course, using fselect path, size from /usr limit 10 is a valid workaround for this use-case- I'm just using head for a quick example. Any similar command that uses SIGPIPE has produced equivalent results. Here's an example that just uses sleep:

$ RUST_BACKTRACE=1 fselect path | sleep 1
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', src/libstd/io/stdio.rs:690:9
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:39
   1: std::sys_common::backtrace::_print
             at src/libstd/sys_common/backtrace.rs:70
   2: std::panicking::default_hook::{{closure}}
             at src/libstd/sys_common/backtrace.rs:58
             at src/libstd/panicking.rs:200
   3: std::panicking::default_hook
             at src/libstd/panicking.rs:215
   4: std::panicking::rust_panic_with_hook
             at src/libstd/panicking.rs:478
   5: std::panicking::continue_panic_fmt
             at src/libstd/panicking.rs:385
   6: std::panicking::begin_panic_fmt
             at src/libstd/panicking.rs:340
   7: std::io::stdio::_print
             at src/libstd/io/stdio.rs:690
             at src/libstd/io/stdio.rs:699
   8: fselect::searcher::Searcher::check_file
   9: fselect::searcher::Searcher::visit_dir
  10: fselect::searcher::Searcher::visit_dir
  11: fselect::searcher::Searcher::visit_dir
  12: fselect::searcher::Searcher::visit_dir
  13: fselect::searcher::Searcher::visit_dir
  14: fselect::searcher::Searcher::visit_dir
  15: fselect::searcher::Searcher::list_search_results
  16: fselect::main
  17: std::rt::lang_start::{{closure}}
  18: std::panicking::try::do_call
             at src/libstd/rt.rs:49
             at src/libstd/panicking.rs:297
  19: __rust_maybe_catch_panic
             at src/libpanic_unwind/lib.rs:92
  20: std::rt::lang_start_internal
             at src/libstd/panicking.rs:276
             at src/libstd/panic.rs:388
             at src/libstd/rt.rs:48
  21: main
  22: __libc_start_main
  23: _start

I'm not a rust programmer but from skimming the documentation about std::io::stdio::_print and the source of the check_file function, I think it's not set up to handle SIGPIPE and terminate early. I'm running fselect version 0.6.3 installed via source using cargo.

@jhspetersson
Copy link
Owner

It turned out to be long standing "bug" or "undocumented behavior" (opinions differ) of Rust's stdlib (rust-lang/rust#24821).

Thank you very match for reporting the panic! Made it work with head and friends. Now fselect doesn't go nuts on pipe limits.

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

2 participants