diff --git a/clients/rust/crates/mxgw-cli/src/main.rs b/clients/rust/crates/mxgw-cli/src/main.rs index f510851..957815e 100644 --- a/clients/rust/crates/mxgw-cli/src/main.rs +++ b/clients/rust/crates/mxgw-cli/src/main.rs @@ -465,13 +465,32 @@ enum CliValueType { String, } -#[tokio::main] -async fn main() -> ExitCode { +/// Entry point. The real work runs on a dedicated thread with a large stack: +/// clap's derive-generated argument parser is deeply recursive, and in debug +/// builds (no inlining) parsing the `Command` enum can exhaust the default +/// 8 MiB main-thread stack as the enum grows. A 32 MiB worker stack keeps the +/// CLI robust regardless of build profile or future subcommand growth. +fn main() -> ExitCode { + let worker = std::thread::Builder::new() + .name("mxgw-cli".to_owned()) + .stack_size(32 * 1024 * 1024) + .spawn(run) + .expect("failed to spawn the CLI worker thread"); + worker.join().expect("the CLI worker thread panicked") +} + +fn run() -> ExitCode { let cli = Cli::parse(); - let result = match cli.command { - Command::Batch => run_batch().await, - command => dispatch(command).await, - }; + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("failed to build the Tokio runtime"); + let result = runtime.block_on(async { + match cli.command { + Command::Batch => run_batch().await, + command => dispatch(command).await, + } + }); match result { Ok(()) => ExitCode::SUCCESS, Err(error) => {