1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
use super::*;
use crate::syscalls::*;
/// ### `proc_exit()`
/// Terminate the process normally. An exit code of 0 indicates successful
/// termination of the program. The meanings of other values is dependent on
/// the environment.
/// Inputs:
/// - `ExitCode`
/// Exit code to return to the operating system
#[instrument(level = "trace", skip_all)]
pub fn proc_exit<M: MemorySize>(
mut ctx: FunctionEnvMut<'_, WasiEnv>,
code: ExitCode,
) -> Result<(), WasiError> {
debug!(%code);
// If we are in a vfork we need to return to the point we left off
if let Some(mut vfork) = ctx.data_mut().vfork.take() {
// Restore the WasiEnv to the point when we vforked
vfork.env.swap_inner(ctx.data_mut());
std::mem::swap(vfork.env.as_mut(), ctx.data_mut());
let mut child_env = *vfork.env;
child_env.owned_handles.push(vfork.handle);
// Terminate the child process
child_env.process.terminate(code);
// Jump back to the vfork point and current on execution
let child_pid = child_env.process.pid();
let memory_stack = vfork.memory_stack.freeze();
let rewind_stack = vfork.rewind_stack.freeze();
let store_data = vfork.store_data;
unwind::<M, _>(ctx, move |mut ctx, _, _| {
// Now rewind the previous stack and carry on from where we did the vfork
match rewind::<M, _>(
ctx,
memory_stack,
rewind_stack,
store_data,
ForkResult {
pid: child_pid.raw() as Pid,
ret: Errno::Success,
},
) {
Errno::Success => OnCalledAction::InvokeAgain,
err => {
warn!("fork failed - could not rewind the stack - errno={}", err);
OnCalledAction::Trap(Box::new(WasiError::Exit(err.into())))
}
}
})?;
return Ok(());
}
// Otherwise just exit
Err(WasiError::Exit(code))
}