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

Tracking issue for std::io::set_panic and set_print #31343

Closed
SimonSapin opened this issue Feb 1, 2016 · 27 comments
Closed

Tracking issue for std::io::set_panic and set_print #31343

SimonSapin opened this issue Feb 1, 2016 · 27 comments
Labels
A-error-handling Area: Error handling A-fmt Area: std::fmt A-io Area: std::io, std::fs, std::net and std::path B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@SimonSapin
Copy link
Contributor

std::io contains these two public unstable functions:

/// Resets the thread-local stderr handle to the specified writer
///
/// This will replace the current thread's stderr handle, returning the old
/// handle. All future calls to `panic!` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new threads; the default
/// output handle is to the process's stderr stream.
pub fn set_panic(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {}

/// Resets the thread-local stdout handle to the specified writer
///
/// This will replace the current thread's stdout handle, returning the old
/// handle. All future calls to `print!` and friends will emit their output to
/// this specified handle.
///
/// Note that this does not need to be called for all new threads; the default
/// output handle is to the process's stdout stream.
pub fn set_print(sink: Box<Write + Send>) -> Option<Box<Write + Send>> {}

They both have #[doc(hidden)]. Anyone knows why?

The also both have:

#[unstable(feature = "set_stdio",
           reason = "this function may disappear completely or be replaced \
                     with a more general mechanism",
           issue = "0")]

Their functionality is evidently useful, since the test crate uses them to capture the output of tests on only show it when they fail. External test harnesses would likely want to have similar functionality.

This issue is about eventually stabilizing either these functions or a more general mechanism.

For set_panic, that mechanism might be panic handlers (#30449) though it would be nice to be able to not duplicate most of the work done in the default handler just to change the output stream. This still leaves set_print.

@alexcrichton
Copy link
Member

This is legacy behavior on behalf of libtest. The set_panic function should be subsumed by panic::set_handler, and set_print is just to have a nice testing experience.

I don't think we should stabilize either of these (as evident by issue = "0"), and this just requires design work to figure out what we can do to replace this functionality.

@retep998
Copy link
Member

retep998 commented Feb 1, 2016

@DanielKeep was specifically interested in set_print as he was working on a library that automatically interprets all escape codes written to stdout and replaces them with calls to the Windows Console API.

@DanielKeep
Copy link
Contributor

Currently, the code for doing this (replacing stdout) is platform-specific and really brittle (see ansi_interpreter win32/intercept.rs). It basically has to do an end-run-around behind libstd's back, swapping out the OS level handles and hoping that no one has touched IO yet... because if they have, then libstd will have already cached the "true" handles, and none of this will work.

Because of libstd's caching behaviour, the only way I can see to do this properly is to be able to explicitly replace the output writer.

Also, consider that you often want to redirect stdout/stderr when working with GUI applications, either to an internal buffer or a log file. Remember that on Windows, GUI applications don't have the standard IO handles connected to anything.

One point to note, however, is that the interception I'm doing is process-wide, whereas I believe set_print is per-thread. Both are useful, though; something like this would be handy:

fn set_process_stdout<W: Write + IntoRawFd>(write: W) -> io::Result<()> { ... }
fn set_thread_stdout<W: Write>(write: W) -> io::Result<()> { ... }

@nagisa
Copy link
Member

nagisa commented Feb 2, 2016

The two functions in the original report were added as a short term hack and are not intended for stabilisation consideration. If the functionality is desired, an RFC with a proper proposal should be created IMO.

@SimonSapin
Copy link
Contributor Author

If this is a short term hack, what will the test crate use long term to capture test output?

@nagisa
Copy link
Member

nagisa commented Feb 3, 2016

What will the test crate use long term to capture test output?

What test crate is using is an implementation detail of (currently) internal component. I suppose test crate would start using the newly introduced stable functions once those become available.

I do not argue against including this sort of functionality into libstd, but to me it sounds like there should be more design process for this and the process in question happens with RFCs (e.g. one obvious solution is to have something based on dup2 on unixes).

@tomaka
Copy link
Contributor

tomaka commented Apr 18, 2016

For the record, the stdout and stderr are ignored when running an Android app.
android-rs-glue is using this feature to redirect stdout/stderr to Android's logging system.

EDIT: in fact no longer the case.

@BartMassey
Copy link
Contributor

For the record, see issue #35136 for an example where the test runner fouls up my test via set_print redirection.

I would prefer to see set_print and set_panic replaced by the test runner running its crates in a child process it controls, ala http://gitlab.com/BartMassey/ptyknot, but I'm not sure how that would work on Windows.

@brson brson added the B-unstable Blocker: Implemented in the nightly compiler and unstable. label Mar 1, 2017
@steveklabnik steveklabnik added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed A-libs labels Mar 24, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. label Jul 22, 2017
@SecondNature
Copy link

set_print() doesn't capture io through std::io::write(). Consider adding set_write() or perhaps making internal set_stdio() , if that would achieve the same result, public would provide io::write() capture.

@SimonSapin
Copy link
Contributor Author

@SecondNature There is no write() function in std::io. Are you referring to something else? (Perhaps provide a code example?)

@SecondNature
Copy link

Yes std::io::write() doesn't exist. My mistake. std::writeln!() redirection is required. Can capture println!() with set_print() but can't capture std::writeln!() as no set_write().

@SimonSapin
Copy link
Contributor Author

The writeln! macro takes a "destination" as a first parameter. If that destination is std::io::stdout(), then the redirection applies today. (Because it is part of stdout(), unrelated to writeln!.) When using writeln! with a different destination, such as an open file, I think the redirection should not apply. Why would it?

@KodrAus
Copy link
Contributor

KodrAus commented Sep 24, 2018

We ran into a quirk of set_print in rust-cli/env_logger#107. There's some surprising behaviour when using the stdout and stderr functions to write to the stream directly during tests, because they aren't using the potentially shimmed LOCAL_STDOUT and LOCAL_STDERR and won't be captured. I think we'd definitely need to explore what the role of the set_print function would be, beyond being a hacked implementation detail so that tests can capture output in a more robust way.

@mcandre
Copy link

mcandre commented Dec 26, 2018

Would like to see these stabilized, so that Rust can produce CloudABI binaries without requiring nightly

@SimonSapin
Copy link
Contributor Author

@mcandre Could you say more about how and why these functions are required for CloudABI?

@viftodi
Copy link

viftodi commented Feb 13, 2019

Hello,

I think there is a huge difference between an "unstable" feauture such as set_print which has been basically unchanged for years and is used by cargo test and other experimental unstable feautures.

I think either rust should allow certain unstable features to be used in stable as well with a warning, set_print being one example, or set_print should have the unstable removed.

I really need this and it's really a shame that I can't do it at all in rust without being forced to use nightly

@SonnyX
Copy link

SonnyX commented Apr 3, 2019

I would like to see a stabilized implementation of this so that libraries such as gag would be able to become cross-platform in a reliable way.

@wdanilo
Copy link

wdanilo commented Oct 31, 2019

I would also love to see that stabilized. The set_print is insanely useful when targetting WASM, so we can use prints to ad-hoc debug code easily.

@KodrAus
Copy link
Contributor

KodrAus commented Nov 8, 2019

I think there is a huge difference between an "unstable" feauture such as set_print which has been basically unchanged for years and is used by cargo test and other experimental unstable feautures.

I'm not really sure set_print is something we'd actually want stabilized as-is. On the one hand it has been left unchanged for a really long time so seems like it must be stable. On the other hand it's also #[doc(hidden)], so is thoroughly undiscoverable and hasn't received much attention.

So rather than stabilize set_print, I think it would be better to mostly pretend it doesn't exist and explore the design space for configuring a "global print target" from scratch (maybe taking inspiration from global allocators?)

@MartinKavik
Copy link

I and other guys agree with @wdanilo - it would be super useful for WASM apps.
See this issue in Seed framework.

@KodrAus KodrAus added Libs-Tracked Libs issues that are tracked on the team's project board. A-error-handling Area: Error handling labels Jul 31, 2020
@KodrAus KodrAus added A-io Area: std::io, std::fs, std::net and std::path A-fmt Area: std::fmt labels Jul 31, 2020
@m-ou-se
Copy link
Member

m-ou-se commented Mar 31, 2021

Closing this, since these functions no longer exist since 1.50 (#78714).

@m-ou-se m-ou-se closed this as completed Mar 31, 2021
@MartinKavik
Copy link

@m-ou-se I see you've done some changes related to set_print / set_output_capture so I assume you have the best knowledge about them now.

Could you please write us about future plans with println-like functions and wasm? I often need to resolve "silently failing" println calls in web apps and it's confusing for beginners and even for me when I switch context between backend and frontend development.

Can we help somehow to make println-like function work in wasm?

Thank you!

@m-ou-se
Copy link
Member

m-ou-se commented Apr 2, 2021

@MartinKavik There are no concrete plans here. The original feature (set_print) was only meant for tests, and was (ab)usable (behind a nightly feature gate) for a few other purposes as well. A mechanism for intercepting output from outside std/test would have to go through an RFC, but I'm not sure if that's the right solution here.

In general, the situation of wasm in the standard library is pretty bad. Almost everything from std compiles fine but silently does nothing or does not work at runtime. (The wasi and emscripten targets do have real implementations for some of them though.) Effectively, we only have core and alloc for wasm, and the rest of std is just empty placeholders.

Ping @alexcrichton: I believe you know more about the situation of wasm in the rust standard library.

@alexcrichton
Copy link
Member

Unfortunately there's no real story for something like println! to work on the wasm32-unknown-unknown target. Panics can work, but only via the panic hook mechanism. It's not a fantastic situation for for better support I'd recommend the wasm32-wasi target or your own custom println macro which goes to the console.

@PriamX
Copy link

PriamX commented Oct 12, 2022

Say, I'm entirely new to rust, trying to get encrusted going, which, in turn, uses wasm-glue (doc.rs here)

In wasm-glue's source file lib.rs, it's apparently still using io::set_print() and io::set_panic(), so it won't compile up. According to this tracker those functions have been deprecated since v1.50.

What is the replacement? Being new to rust, and poking through the docs, I'm not finding anything obvious, thinking this change was done fairly quietly. I'd like to submit an update to wasm-glue.

Thanks.

@m-ou-se
Copy link
Member

m-ou-se commented Oct 12, 2022

According to this tracker those functions have been deprecated since v1.50.

There's no replacement, because these functions never actually existed in stable Rust at all. The code you linked relied on a nightly feature, making use of an internal implementation detail of some older versions of Rust that wasn't meant for that purpose.

A solution might be for that crate to provide its own print and println macros.

Another solution could be to add some new feature to Rust's standard library (for wasm only, or for all platforms) that can be used for this. A design for that could be proposed in an RFC.

@PriamX
Copy link

PriamX commented Oct 12, 2022

Thank you for the reply. It's not my code, I was just hoping to be able to contribute a fix for it. I'd be comfortable developing a fix to the existing wasm-glue code, but since I'm new to rust, designing a new solution may be a bit out of my wheelhouse right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-error-handling Area: Error handling A-fmt Area: std::fmt A-io Area: std::io, std::fs, std::net and std::path B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. Libs-Tracked Libs issues that are tracked on the team's project board. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests