0

I am deploying a Rust binary on Windows 10, though the source code should be OS agnostic. When I run a smoke test which invokes the main function of my crate, it fails:

In tests\main.rs:

use std::process::Command;
use std::process::Stdio;

#[test]
fn my_test() -> Result<(), Box<dyn std::error::Error>> {
    let mut cmd = Command::main_binary()?;
    // Omitted some project specific code
    cmd.stderr(Stdio::inherit()).stdout(Stdio::inherit()).unwrap();
}

Note that Command is from the assert_cmd library (version 0.10).

The same goes for running the .exe file in the target folder, which, when given the same input as any of my other tests, gives:

C:\path\to\project\target\x86_64-pc-windows-msvc\debug> my_project.ext -i path\to\vetted\output

started
starting memory_intensive_function

thread `main` has overflowed its stack

The main function, however, is not much more than a thin wrapper which parses command line arguments and then internally invokes some functions:

In src\main.rs

pub fn main() -> Result<(), String> {
    println!("started")
    // parse command line arguments
    println!("starting memory_intensive_function");
    memory_intensive_function(/* command line arguments here */)?;
    println!("completed memory intensive function");
}

The last print statement never prints anything. The weird thing is that I have several tests, 330 in total, of which 40 or so invoke the memory_intensive_function() directly, and all of these run just fine. Is there some behavior in Rust that I am not aware of?

I have been toying a bit with the idea of running memory_intensive_function() on a different blocking thread, but I'm not sure how that would help.

It should be noted that substantially rewriting this function is not really an option (though general tips or guidelines are welcome).

tl;dr A lot of tests which call a memory intensive function works fine, but using this function in main causes it to crash.

Joël Abrahams
  • 379
  • 4
  • 15
  • 4
    It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Mar 02 '20 at 21:45
  • See also [cargo test --release causes a stack overflow. Why doesn't cargo bench?](https://stackoverflow.com/q/42955243/155423) – Shepmaster Mar 02 '20 at 21:50
  • What is `Command::main_binary`? It's not defined in `std` that I can tell. *The last print statement never prints anything* -- does the *first* one? – trent Mar 02 '20 at 21:51
  • The first one does indeed print. – Joël Abrahams Mar 02 '20 at 21:52
  • 2
    See also [Thread Stack Size (MSDN)](https://learn.microsoft.com/en-us/windows/win32/procthread/thread-stack-size) / [`std::thread`](https://doc.rust-lang.org/std/thread/index.html#stack-size). The default stack size on Windows is 1MiB (e.g. `main`). The default stack size for a Rust thread is 2MiB (e.g. tests). – Shepmaster Mar 02 '20 at 21:53
  • @Shepmaster I'm going to do my best, but it is really difficult to reproduce this particular problem online. If I will do my best, and if I do manage to find an answer before then I'll post it here (in case someone runs into the same issue). – Joël Abrahams Mar 02 '20 at 21:54
  • @JoëlAbrahams if you re-read my comment: *on the Rust Playground **if possible**, otherwise in a brand new Cargo project*. There is then a link to a section of tips that you can use to delete all the irrelevant code from your project to produce the [MRE]. – Shepmaster Mar 02 '20 at 21:55
  • @Shepmaster oh sorry, but I think that is what I meant, more that it will take some time to write a specific function which runs fine in tests and not when main is invoked (as in, the behaviour itself difficult to reduce and reproduce), if that makes sense. But I was not aware that the test threads got 2MiB instead of 1MiB, so that's probably what causes it then. – Joël Abrahams Mar 02 '20 at 21:58
  • I mean, you already have that: it's what you are asking about. The hard work is in deleting everything else that isn't related. That's what the linked tips help with. – Shepmaster Mar 02 '20 at 22:00

0 Answers0