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

Prevent broken pipes causing ICEs #49606

Merged
merged 1 commit into from
Apr 16, 2018
Merged

Prevent broken pipes causing ICEs #49606

merged 1 commit into from
Apr 16, 2018

Conversation

varkor
Copy link
Member

@varkor varkor commented Apr 2, 2018

As the private std::io::print_to panics if there is an I/O error, which is used by println!, the compiler would ICE if one attempted to use a broken pipe (e.g. rustc --help | false). This introduces a new (private) macro try_println! which allows us to avoid this.

As a side note, it seems this macro might be useful publicly (and actually there seems to be a crate specifically for this purpose), though that can probably be left for a future discussion.

One slight alternative approach would be to simply early exit without an error (i.e. exit code 0), which this comment suggests is the usual approach. I've opted not to take that approach initially, because I think it's more helpful to know when there is a broken pipe.

Fixes #34376.

@pietroalbini pietroalbini added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 2, 2018
@nikomatsakis
Copy link
Contributor

Maybe we should just use that crate? I guess this is minimal enough code it's probably not worth adding an external dependency.

Copy link
Contributor

@nikomatsakis nikomatsakis left a comment

Choose a reason for hiding this comment

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

I feel like I'd rather not entable libcore/libstd if we can avoid it. Thoughts?

#[doc(hidden)]
pub fn _try_print(args: fmt::Arguments) -> io::Result<()> {
try_print_to(args, &LOCAL_STDOUT, stdout)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

seems fine, but I feel like we could easily use stable APIs to build this, no? Like, can't we just make librustc_driver use write! or something?

Copy link
Member Author

Choose a reason for hiding this comment

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

The primary reason I did it this way was to make sure try_println! had ensured identical behaviour as println! (apart from the panic behaviour). I'm not sure how important this is in practice, but felt that it was generally a good idea to keep things familiar, so as not to introduce some inconsistency that would lead to a different issue in the future. (Plus, if we ever want to make such functionality public, it's trivial.)

If you think this is overcomplicating things, though, I could write inside librustc_driver instead, yeah.

@nikomatsakis nikomatsakis added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 4, 2018
@varkor
Copy link
Member Author

varkor commented Apr 4, 2018

Maybe we should just use that crate? I guess this is minimal enough code it's probably not worth adding an external dependency.

Yes, it really is very minimal. Additionally, the behaviour of the crate isn't exactly the same as println! (#49606 (comment) again relevant).

@nikomatsakis
Copy link
Contributor

What's an example of how println! and write! might differ?

@varkor
Copy link
Member Author

varkor commented Apr 6, 2018

My main concern was:

print_to(args, &LOCAL_STDOUT, stdout, "stdout");

write! wouldn't have this stdout fallback, though I'm not sure if this would ever actually be an issue from the context of librustc_driver. I'm not really familiar with the context.

@nikomatsakis
Copy link
Contributor

OK, well, I don't really care that much either way. r=me for the compiler bits, but I'd like somebody from @rust-lang/libs to at least glance over the changes to println!.

r? @alexcrichton

@alexcrichton
Copy link
Member

I'm personally a little concerned about the long-term maintainability of a solution like this, for example this doesn't change anything in src/librustc_errors, but doesn't that mean diagnostics will hit broken pipes? If we want to terminate on EPIPE I think we should just reenable the signal handler, right?

@varkor
Copy link
Member Author

varkor commented Apr 8, 2018

@alexcrichton: why/where was the signal handler originally disabled?

@sfackler
Copy link
Member

sfackler commented Apr 8, 2018

@varkor

pub fn init() {

It's disabled by default because it only really makes sense for CLI programs that only touch stdin/stdout/stderr and don't do any e.g. networking.

@varkor
Copy link
Member Author

varkor commented Apr 10, 2018

@sfackler: Thanks! I didn't realise that EPIPE triggered SIGPIPE.

@alexcrichton: Are there any reasons to want to ignore SIGPIPE (i.e. is completely removing the signal handler okay)?

Also, are we happy with just exiting, or do we want to trigger an message?

@varkor
Copy link
Member Author

varkor commented Apr 10, 2018

Now an EPIPE will simply terminate rustc/rustdoc, by (re-)overriding the SIGPIPE signal handler.

unsafe {
// Set the SIGPIPE signal handler, so that an EPIPE
// will cause rustc to terminate, as expected.
assert!(signal(libc::SIGPIPE, libc::SIG_DFL) != libc::SIG_ERR);
Copy link
Member

Choose a reason for hiding this comment

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

I think this may not compile on Windows, and could the logic between rustc and rustdoc be shared?

@pietroalbini pietroalbini added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 16, 2018
@pietroalbini
Copy link
Member

Ping from triage @alexcrichton! The author addressed your comments!

@alexcrichton
Copy link
Member

@bors: r+

er sorry @varkor, I missed the update!

@bors
Copy link
Contributor

bors commented Apr 16, 2018

📌 Commit 7ab31f6 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 Apr 16, 2018
kennytm added a commit to kennytm/rust that referenced this pull request Apr 16, 2018
Prevent broken pipes causing ICEs

As the private `std::io::print_to` panics if there is an I/O error, which is used by `println!`, the compiler would ICE if one attempted to use a broken pipe (e.g. `rustc --help | false`). This introduces a new (private) macro `try_println!` which allows us to avoid this.

As a side note, it seems this macro might be useful publicly (and actually there seems to be [a crate specifically for this purpose](https://crates.io/crates/try_print/)), though that can probably be left for a future discussion.

One slight alternative approach would be to simply early exit without an error (i.e. exit code `0`), which [this comment](rust-lang#34376 (comment)) suggests is the usual approach. I've opted not to take that approach initially, because I think it's more helpful to know when there is a broken pipe.

Fixes rust-lang#34376.
bors added a commit that referenced this pull request Apr 16, 2018
Rollup of 8 pull requests

Successful merges:

 - #49555 (Inline most of the code paths for conversions with boxed slices)
 - #49606 (Prevent broken pipes causing ICEs)
 - #49646 (Use box syntax instead of Box::new in Mutex::remutex on Windows)
 - #49647 (Remove `underscore_lifetimes` and `match_default_bindings` from active feature list)
 - #49931 (Fix incorrect span in `&mut` suggestion)
 - #49959 (rustbuild: allow building tools with debuginfo)
 - #49965 (Remove warning about f64->f32 cast being potential UB)
 - #49994 (Remove unnecessary indentation in rustdoc book codeblock.)

Failed merges:
@bors bors merged commit 7ab31f6 into rust-lang:master Apr 16, 2018
@varkor varkor deleted the pipe-repair branch April 16, 2018 23:23
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 24, 2022
…h726

rustc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in one place: `rustc` itself.

It is easy to manually verify this change. If you remove `#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help | false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears again.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Not sure exactly how to label this PR. Going with T-libs for now since this is a T-libs feature.

`@rustdoc` labels +T-libs
JohnTitor pushed a commit to JohnTitor/rust that referenced this pull request Oct 24, 2022
…triddle

rustdoc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

Do what was already done for `rustc` in rust-lang#102587, namely start using `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`.

After this has been merged, we can completely remove `rustc_driver::set_sigpipe_handler`.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Verification of this change
---------------------------

1. Remove `#[unix_sigpipe = "sig_dfl"]`
1. Run `./x.py build`
1. Run `./build/aarch64-apple-darwin/stage1/bin/rustdoc --help | false`
1. Observe ICE
1. Add back `#[unix_sigpipe = "sig_dfl"]`
1. Run `./x.py build`
1. Run `./build/aarch64-apple-darwin/stage1/bin/rustdoc --help | false`
1. Observe ICE fixed

`@rustbot` labels +T-rustdoc
JohnTitor pushed a commit to JohnTitor/rust that referenced this pull request Oct 24, 2022
…triddle

rustdoc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

Do what was already done for `rustc` in rust-lang#102587, namely start using `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`.

After this has been merged, we can completely remove `rustc_driver::set_sigpipe_handler`.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Verification of this change
---------------------------

1. Remove `#[unix_sigpipe = "sig_dfl"]`
1. Run `./x.py build`
1. Run `./build/aarch64-apple-darwin/stage1/bin/rustdoc --help | false`
1. Observe ICE
1. Add back `#[unix_sigpipe = "sig_dfl"]`
1. Run `./x.py build`
1. Run `./build/aarch64-apple-darwin/stage1/bin/rustdoc --help | false`
1. Observe ICE fixed

``@rustbot`` labels +T-rustdoc
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 25, 2022
…h726

rustc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in one place: `rustc` itself.

It is easy to manually verify this change. If you remove `#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help | false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears again.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Not sure exactly how to label this PR. Going with T-libs for now since this is a T-libs feature.

``@rustdoc`` labels +T-libs
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 25, 2022
…h726

rustc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in one place: `rustc` itself.

It is easy to manually verify this change. If you remove `#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help | false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears again.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Not sure exactly how to label this PR. Going with T-libs for now since this is a T-libs feature.

```@rustdoc``` labels +T-libs
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 25, 2022
…h726

rustc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in one place: `rustc` itself.

It is easy to manually verify this change. If you remove `#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help | false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears again.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Not sure exactly how to label this PR. Going with T-libs for now since this is a T-libs feature.

````@rustdoc```` labels +T-libs
RalfJung pushed a commit to RalfJung/miri that referenced this pull request Oct 25, 2022
rustc: Use `unix_sigpipe` instead of `rustc_driver::set_sigpipe_handler`

This is the first (known) step towards starting to use `unix_sigpipe` in the wild. Eventually, `rustc_driver::set_sigpipe_handler` can be removed and all clients can use `unix_sigpipe` instead.

For now we just start using `unix_sigpipe` in one place: `rustc` itself.

It is easy to manually verify this change. If you remove `#[unix_sigpipe = "sig_dfl"]` and run `./x.py build` you will get an ICE when you do `./build/x86_64-unknown-linux-gnu/stage1/bin/rustc --help | false`. Add back `#[unix_sigpipe = "sig_dfl"]` and the ICE disappears again.

PR that added `set_sigpipe_handler`: rust-lang/rust#49606

Tracking issue for `unix_sigpipe`: #97889

Not sure exactly how to label this PR. Going with T-libs for now since this is a T-libs feature.

````@rustdoc```` labels +T-libs
compiler-errors added a commit to compiler-errors/rust that referenced this pull request Oct 25, 2022
…, r=tmiasko

Remove `rustc_driver::set_sigpipe_handler()`

Its usage was removed in rust-lang#102587 and rust-lang#103495, so we do not need to keep it around any longer. According to [preliminary input](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Find.20.60rustc_driver.60.20dependent.20projects.3F/near/304490764), we do not need to worry about any deprecation cycle for this explicitly unstable API, and can just straight up remove it.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Migration instructions for any remaining clients
---

Change from

```rust
#![feature(rustc_private)]

extern crate rustc_driver;

fn main() {
    rustc_driver::set_sigpipe_handler();
    // ...
```

to

```rust
#![feature(unix_sigpipe)]

#[unix_sigpipe = "sig_dfl"]
fn main() {
    // ...
```

`@rustbot` labels +T-compiler
Dylan-DPC added a commit to Dylan-DPC/rust that referenced this pull request Oct 26, 2022
…, r=tmiasko

Remove `rustc_driver::set_sigpipe_handler()`

Its usage was removed in rust-lang#102587 and rust-lang#103495, so we do not need to keep it around any longer. According to [preliminary input](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Find.20.60rustc_driver.60.20dependent.20projects.3F/near/304490764), we do not need to worry about any deprecation cycle for this explicitly unstable API, and can just straight up remove it.

PR that added `set_sigpipe_handler`: rust-lang#49606

Tracking issue for `unix_sigpipe`: rust-lang#97889

Migration instructions for any remaining clients
---

Change from

```rust
#![feature(rustc_private)]

extern crate rustc_driver;

fn main() {
    rustc_driver::set_sigpipe_handler();
    // ...
```

to

```rust
#![feature(unix_sigpipe)]

#[unix_sigpipe = "sig_dfl"]
fn main() {
    // ...
```

``@rustbot`` labels +T-compiler
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.

6 participants