wasmer_wasix/runners/dcgi/
callbacks.rs

1use std::sync::Arc;
2
3use super::*;
4use crate::runners::wcgi::{self, CreateEnvConfig, CreateEnvResult, RecycleEnvConfig};
5use virtual_fs::NullFile;
6use wasmer_wasix_types::types::{__WASI_STDERR_FILENO, __WASI_STDIN_FILENO, __WASI_STDOUT_FILENO};
7
8#[derive(Debug, Clone)]
9pub struct DcgiCallbacks {
10    inner: Arc<dyn wcgi::Callbacks>,
11    factory: DcgiInstanceFactory,
12}
13
14impl DcgiCallbacks {
15    pub fn new<C>(factory: DcgiInstanceFactory, inner: C) -> Self
16    where
17        C: wcgi::Callbacks,
18    {
19        Self {
20            inner: Arc::new(inner),
21            factory,
22        }
23    }
24}
25
26#[async_trait::async_trait]
27impl wcgi::Callbacks for DcgiCallbacks {
28    fn started(&self, abort: AbortHandle) {
29        self.inner.started(abort)
30    }
31
32    fn on_stderr(&self, stderr: &[u8]) {
33        self.inner.on_stderr(stderr)
34    }
35
36    fn on_stderr_error(&self, error: std::io::Error) {
37        self.inner.on_stderr_error(error)
38    }
39
40    async fn recycle_env(&self, conf: RecycleEnvConfig) {
41        tracing::debug!("recycling DCGI instance");
42
43        // The stdio have to be reattached on each call as they are
44        // read to completion (EOF) during nominal flows
45        conf.env
46            .state
47            .fs
48            .swap_file(__WASI_STDIN_FILENO, Box::<NullFile>::default())
49            .ok();
50        conf.env
51            .state
52            .fs
53            .swap_file(__WASI_STDOUT_FILENO, Box::<NullFile>::default())
54            .ok();
55        conf.env
56            .state
57            .fs
58            .swap_file(__WASI_STDERR_FILENO, Box::<NullFile>::default())
59            .ok();
60
61        // Now we make the instance available for reuse
62        self.factory.release(conf).await;
63    }
64
65    async fn create_env(&self, mut conf: CreateEnvConfig) -> anyhow::Result<CreateEnvResult> {
66        tracing::debug!("attempting to acquire existing DCGI instance");
67
68        if let Some(res) = self.factory.acquire(&mut conf).await {
69            tracing::debug!("found existing DCGI instance");
70            return Ok(res);
71        }
72
73        let mut ret = self.inner.create_env(conf).await;
74
75        if let Ok(ret) = ret.as_mut() {
76            // We disable the cleanup to prevent the instance so that the
77            // resources can be reused
78            ret.env.disable_fs_cleanup = true;
79        }
80
81        ret
82    }
83}