wasmer_wasix/syscalls/wasix/
context_destroy.rs

1use crate::{WasiEnv, WasiError};
2use tracing::instrument;
3use wasmer::{AsStoreRef, FunctionEnvMut, MemoryView};
4use wasmer_wasix_types::wasi::Errno;
5
6/// Destroy a suspended or terminated context
7///
8/// After a successful call its identifier becomes invalid and its
9/// resources are released. Destroying an already deleted context is a no-op.
10///
11/// Refer to the wasix-libc [`wasix/context.h`] header for authoritative
12/// documentation.
13///
14/// [`wasix/context.h`]: https://github.com/wasix-org/wasix-libc/blob/main/libc-bottom-half/headers/public/wasix/context.h
15#[instrument(level = "trace", skip(ctx), ret)]
16pub fn context_destroy(
17    mut ctx: FunctionEnvMut<'_, WasiEnv>,
18    target_context_id: u64,
19) -> Result<Errno, WasiError> {
20    WasiEnv::do_pending_operations(&mut ctx)?;
21
22    let env = ctx.data();
23    let memory: MemoryView<'_> = unsafe { env.memory_view(&ctx) };
24
25    // Verify that we are in an async context
26    let environment = match &env.context_switching_environment {
27        Some(c) => c,
28        None => {
29            tracing::warn!(
30                "The WASIX context-switching API is only available in a context-switching environment"
31            );
32            return Ok(Errno::Notsup);
33        }
34    };
35
36    let own_context_id = environment.active_context_id();
37    let main_context_id = environment.main_context_id();
38
39    if own_context_id == target_context_id {
40        tracing::trace!(
41            "Context {} tried to delete itself, which is not allowed",
42            target_context_id
43        );
44        return Ok(Errno::Inval);
45    }
46
47    if target_context_id == main_context_id {
48        tracing::trace!(
49            "Context {} tried to delete the main context, which is not allowed",
50            own_context_id
51        );
52        return Ok(Errno::Inval);
53    }
54
55    let removed_unblocker = environment.destroy_context(&target_context_id);
56    // As soon as the Sender is dropped, the corresponding context will be able unblocked,
57    // the executor will continue executing it. The context will respond to the
58    // cancelation by terminating gracefully.
59
60    if !removed_unblocker {
61        // Context did not exist, so we do not need to remove it
62        tracing::trace!(
63            "Context {} tried to delete context {} but it is already removed",
64            own_context_id,
65            target_context_id
66        );
67        return Ok(Errno::Success);
68    };
69
70    Ok(Errno::Success)
71}