Skip to main content

dope_runtime/process/
shutdown.rs

1use std::{mem, os::fd};
2
3use dope_core::driver::{life::creation, settings};
4
5use crate::{
6    executor::{self, create},
7    process::{gate, lifecycle, runtime::bus},
8};
9
10/// Shutdown source borrowed from the exact process run that owns this worker.
11///
12/// A proof issued by the standalone shutdown API cannot be retagged as a
13/// production process proof.
14pub struct Shutdown<'run> {
15    pub(in crate::process) source: bus::Tx<'run>,
16}
17
18impl<'run> Shutdown<'run> {
19    pub(super) const fn new(tx: bus::Tx<'run>) -> Self {
20        Self { source: tx }
21    }
22
23    pub(super) fn gate(&self) -> gate::Closed<'run> {
24        gate::Closed::new(self.source)
25    }
26
27    pub fn control(&self) -> lifecycle::Control<'_> {
28        lifecycle::Control::new(self.source.as_fd())
29    }
30
31    pub fn terminal(&self) -> crate::process::Terminal<'run> {
32        crate::process::Terminal {
33            source: self.source,
34        }
35    }
36
37    pub(super) fn attach<'a>(
38        self,
39        executor: Result<executor::Executor, create::Error<'a>>,
40    ) -> Result<executor::Executor<(), Self>, create::Error<'a>> {
41        let terminal = self.terminal();
42        executor
43            .and_then(|executor| executor.shutdown(self).map_err(create::Error::from))
44            .inspect_err(|_| {
45                let _ = terminal.fail();
46            })
47    }
48}
49
50impl executor::Build for Shutdown<'_> {
51    type Shutdown = Self;
52
53    fn try_build(
54        self,
55        attempt: &mut creation::Attempt,
56        config: settings::Config,
57    ) -> Result<executor::Executor<(), Self::Shutdown>, create::Error<'_>> {
58        self.attach(executor::Executor::new(attempt, config))
59    }
60}
61
62impl fd::AsFd for Shutdown<'_> {
63    fn as_fd(&self) -> fd::BorrowedFd<'_> {
64        self.source.as_fd()
65    }
66}
67
68impl crate::executor::Startup for Shutdown<'_> {
69    fn installed(&self) -> Result<(), crate::executor::InstallError> {
70        self.source.installed().map_err(Into::into)
71    }
72
73    fn failed(&self) {
74        let _ = self.terminal().fail();
75    }
76}
77
78const _: () = {
79    assert!(mem::size_of::<Shutdown<'static>>() == mem::size_of::<bus::Tx<'static>>());
80    assert!(mem::align_of::<Shutdown<'static>>() == mem::align_of::<bus::Tx<'static>>());
81};