Skip to content

Commit a8798b6

Browse files
authored
Fix exit code mismatch between wasmtime and lind-boot exit (#856)
* Fix exit code mismatch * Update skipped list * Skip test case * Handle system err return * Fix merge conflicts
1 parent 750ba9a commit a8798b6

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

src/lind-boot/src/lind_wasmtime/execute.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use wasmtime_wasi_threads::WasiThreadsCtx;
4646
/// entrypoint. On successful completion it waits for all cages to exit before
4747
/// shutting down RawPOSIX, ensuring runtime-wide cleanup happens only after the
4848
/// last process terminates.
49-
pub fn execute_wasmtime(lindboot_cli: CliOptions) -> anyhow::Result<Vec<Val>> {
49+
pub fn execute_wasmtime(lindboot_cli: CliOptions) -> anyhow::Result<i32> {
5050
// -- Initialize Lind + RawPOSIX + 3i runtime --
5151
// Initialize the Lind cage counter
5252
let lind_manager = Arc::new(LindCageManager::new(0));
@@ -71,16 +71,25 @@ pub fn execute_wasmtime(lindboot_cli: CliOptions) -> anyhow::Result<Vec<Val>> {
7171
let result = execute_with_lind(lindboot_cli, lind_manager.clone(), CAGE_START_ID as u64);
7272

7373
match result {
74-
Ok(ref _res) => {
74+
Ok(ref ret_vals) => {
7575
// we wait until all other cage exits
7676
lind_manager.wait();
77+
// Interpret the first return value of the Wasm entry point
78+
// as the process exit code. If the module does not explicitly
79+
// return an i32, we treat it as a successful exit (code = 0).
80+
let exit_code = match ret_vals.first() {
81+
Some(Val::I32(code)) => *code,
82+
_ => 0,
83+
};
84+
// Propagate the exit code to the main, which will translate it
85+
// into the host process exit status.
86+
Ok(exit_code)
7787
}
7888
Err(e) => {
89+
// Exit the process
7990
return Err(e);
8091
}
8192
}
82-
83-
result
8493
}
8594

8695
/// Executes a Wasm program *within an existing Lind runtime* as part of an `exec()` path.

src/lind-boot/src/main.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,27 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
7171
// Initialize RawPOSIX and register RawPOSIX syscalls with 3i
7272
rawposix_start(0);
7373

74-
// Execute with user-selected runtime. Can be switched to other runtime implementation
75-
// in the future (e.g.: MPK).
76-
execute_wasmtime(lindboot_cli)?;
74+
// Execute the selected runtime backend and translate its unified
75+
// execution result into a host-level process exit status.
76+
//
77+
// At this layer, we intentionally do NOT interpret Wasm return
78+
// conventions or runtime-specific details. All exit semantics
79+
// (e.g., proc_exit, return values, traps) are already normalized
80+
// inside `execute_wasmtime` into a single `i32` exit code.
81+
//
82+
// This design keeps the runtime backend pluggable (e.g., Wasmtime,
83+
// MPK-based runtime, SGX-enclosed runtime) while preserving a
84+
// consistent host process contract: exit(code) on success,
85+
// If the runtime backend fails before producing a normalized
86+
// program exit code, terminate with EX_SOFTWARE (70) to signal
87+
// a runtime-level failure rather than a cage-provided exit code.
88+
match execute_wasmtime(lindboot_cli) {
89+
Ok(code) => std::process::exit(code),
90+
Err(e) => {
91+
eprintln!("{:?}", e);
92+
std::process::exit(sysdefs::constants::EX_SOFTWARE);
93+
}
94+
}
7795

7896
// after all cage exits, finalize the lind
7997
rawposix_shutdown();

src/sysdefs/src/constants/sys_const.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,27 @@ pub const CLONE_IO: u64 = 0x80000000; /* Clone I/O context. */
209209
/* cloning flags intersect with CSIGNAL so can be used only with unshare and
210210
clone3 syscalls. */
211211
pub const CLONE_NEWTIME: u64 = 0x00000080; /* New time namespace */
212+
213+
// Exit code
214+
// Source: src/glibc/misc/sysexits.h
215+
pub const EX_OK: i32 = 0; /* successful termination */
216+
217+
pub const EX__BASE: i32 = 64; /* base value for error messages */
218+
219+
pub const EX_USAGE: i32 = 64; /* command line usage error */
220+
pub const EX_DATAERR: i32 = 65; /* data format error */
221+
pub const EX_NOINPUT: i32 = 66; /* cannot open input */
222+
pub const EX_NOUSER: i32 = 67; /* addressee unknown */
223+
pub const EX_NOHOST: i32 = 68; /* host name unknown */
224+
pub const EX_UNAVAILABLE: i32 = 69; /* service unavailable */
225+
pub const EX_SOFTWARE: i32 = 70; /* internal software error */
226+
pub const EX_OSERR: i32 = 71; /* system error (e.g., can't fork) */
227+
pub const EX_OSFILE: i32 = 72; /* critical OS file missing */
228+
pub const EX_CANTCREAT: i32 = 73; /* can't create (user) output file */
229+
pub const EX_IOERR: i32 = 74; /* input/output error */
230+
pub const EX_TEMPFAIL: i32 = 75; /* temp failure; user is invited to retry */
231+
pub const EX_PROTOCOL: i32 = 76; /* remote error in protocol */
232+
pub const EX_NOPERM: i32 = 77; /* permission denied */
233+
pub const EX_CONFIG: i32 = 78; /* configuration error */
234+
235+
pub const EX__MAX: i32 = 78; /* maximum listed value */

0 commit comments

Comments
 (0)