-
Notifications
You must be signed in to change notification settings - Fork 226
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
NIF panics when producing too much input in too short of a time #72
Comments
Can you paste some example code that produces this scenario? |
pub fn print_panic<'a>(env: NifEnv<'a>, _args: &Vec<NifTerm<'a>>) -> NifResult<NifTerm<'a>> {
for _ in 0..1000 {
println!("testtesttesttesttesttesttesttesttesttesttesttest");
}
Ok(true.encode(env))
} |
hmm...but this isn't real world use case, is it? Seems only useful for debugging purposes. |
Which is a very real world use case. I have hit this issue numerous times when writing different kinds of NIFs. |
Yeah, this has hit me more than once, just trying to debug misbehaving tests. Rustler can provide its own |
erlnif have some api can provide async thread spawn which can aviod such situations that going to block the beam |
Rustler has APIs like that too, but they don't do anything to solve this problem. I still think just replacing |
cool! |
Using use rustler::{Encoder, NifResult};
use std::io::Write;
fn crash<'a>(env: Env<'a>, _: &[Term]) -> NifResult<Term<'a>> {
let stdout = std::io::stdout();
let mut lock = stdout.lock();
for _ in 0..10000 {
writeln!(&mut lock, "testtesttesttesttesttesttesttesttesttesttesttest");
}
Ok(true.encode(env))
} Of course, this does not solve the problem, as simply increasing the iterations will still lead to panics. 100_000 iterations of the loop above result in a panic here. |
FWIW, I just hit this problem with only a few KB, (one terminal screen full or so, no loops, just individual logging statements), and it cost me a day chasing down where my panic was coming from, as I assumed I had a logic error somewhere. As we may not have good source-level debugging tools for Rust code running inside the BEAM, early development can be highly-dependent on debug messages. That said, there is a workaround to at least avoid the crash: use gag::Redirect;
…
let log = OpenOptions::new()
.truncate(true)
.read(true)
.create(true)
.write(true)
.open("/var/log/…")
.unwrap();
let print_redirect = Redirect::stdout(log).unwrap();
let pd_heap = Box::new(print_redirect);
let _ = Box::into_raw(pd_heap); This has the awkward effect of segregating output of |
I can trigger it reliably with evnu@6d1ce19 if I run it through rust-gdb and an ERTS Debug VM. When running the example directly with rust 1.40 and alacritty, the panic happens very rarely here. The panic happens here, after the output should have been written to stdout: if let Err(e) = result {
panic!("failed printing to {}: {}", label, e);
} Alas, I haven't been able to get the values of
|
@evnu can you swap the use of |
I added
|
I tried to get some more info using
I ran
Error 11 = EAGAIN:
|
Closing, I think we cannot do something here. |
It looks like setting stdio as nonblocking is generally considered bad practice as it not only propagates to external libraries but also affects every program sharing the tty. Turns out it surely had caused other complaints upstream for the reason I mentioned: erlang/otp#3150. It looks like a new tty driver implementation is in the pipeline and will hopefully fix this issue in a future release: erlang/otp@bd0865f. |
Not sure if there is any way to actually fix this. This is probably because Erlang has stdout set to non-blocking mode, and a buffer gets filled up somewhere.
The text was updated successfully, but these errors were encountered: