wasmer_wasix/syscalls/wasix/
stack_restore.rs

1use super::*;
2use crate::syscalls::*;
3
4/// ### `stack_restore()`
5/// Restores the current stack to a previous stack described by its
6/// stack hash.
7///
8/// ## Parameters
9///
10/// * `snapshot_ptr` - Contains a previously made snapshot
11#[instrument(level = "trace", skip_all, ret)]
12pub fn stack_restore<M: MemorySize>(
13    mut ctx: FunctionEnvMut<'_, WasiEnv>,
14    snapshot_ptr: WasmPtr<StackSnapshot, M>,
15    mut val: Longsize,
16) -> Result<(), WasiError> {
17    WasiEnv::do_pending_operations(&mut ctx)?;
18
19    // Read the snapshot from the stack
20    let env = ctx.data();
21    let memory = unsafe { env.memory_view(&ctx) };
22    let snapshot = match snapshot_ptr.read(&memory) {
23        Ok(a) => {
24            trace!("with_ret={}, hash={}, user={}", val, a.hash(), a.user);
25            a
26        }
27        Err(err) => {
28            warn!("failed to read stack snapshot - {}", err);
29            return Err(WasiError::Exit(mem_error_to_wasi(err).into()));
30        }
31    };
32
33    // Perform the unwind action
34    unwind::<M, _>(ctx, move |mut ctx, _, _| {
35        // Let the stack (or fail trying!)
36        let env = ctx.data();
37        if let Some((mut memory_stack, rewind_stack, store_data)) =
38            env.thread.get_snapshot(snapshot.hash())
39        {
40            let env = ctx.data();
41            let memory = unsafe { env.memory_view(&ctx) };
42
43            // Rewind the stack - after this point we must immediately return
44            // so that the execution can end here and continue elsewhere.
45            let pid = ctx.data().pid();
46            let tid = ctx.data().tid();
47
48            let rewind_result = bincode::serialize(&val).unwrap().into();
49            let ret = rewind_ext::<M>(
50                &mut ctx,
51                None, // we do not restore the thread memory as `longjmp`` is not meant to do this
52                rewind_stack,
53                store_data,
54                RewindResultType::RewindWithResult(rewind_result),
55            );
56            match ret {
57                Errno::Success => OnCalledAction::InvokeAgain,
58                err => {
59                    warn!("failed to rewind the stack - errno={}", err);
60                    OnCalledAction::Trap(Box::new(WasiError::Exit(err.into())))
61                }
62            }
63        } else {
64            warn!(
65                "snapshot stack restore failed - the snapshot can not be found and hence restored (hash={})",
66                snapshot.hash()
67            );
68            OnCalledAction::Trap(Box::new(WasiError::Exit(Errno::Unknown.into())))
69        }
70    });
71
72    // Return so the stack can be unwound (which will then
73    // be rewound again but with a different location)
74    Ok(())
75}