wasmer_wasix/syscalls/wasix/
stack_restore.rs

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