Skip to main content

DaemonCommand

Struct DaemonCommand 

Source
pub struct DaemonCommand { /* private fields */ }
Expand description

A daemon to start detached from the calling process.

The child inherits the caller’s environment with the changes made here, in order. Pass an absolute program path: on Windows the search for a bare name differs from Command’s, and batch files are refused.

On Unix the child is a new session leader (setsid): Ctrl-C and the hangup of the caller’s terminal do not reach it. Every descriptor above stderr is closed across the exec, so it starts with only its standard streams.

On Windows it gets its own hidden console and a new process group, and inherits only its three standard handles, so no pipe the caller holds stays open because of it. It is also taken out of the caller’s job object when that job allows it.

A readiness channel is the one exception on Unix: its descriptor also survives the exec. On Windows the daemon opens that channel by name and inherits nothing for it.

§Job objects on Windows

A job can forbid its processes’ children from leaving it, and cargo’s does: cargo puts itself and every child in a job that kills them all when cargo is interrupted, without allowing breakaway. A daemon started under such a job stays in it and dies with the caller on Ctrl-C, whatever this builder does. DaemonChild::in_callers_job reports that case so the caller can say so. The only way out is to start the daemon from outside the job, for example through a scheduled task or a service.

Implementations§

Source§

impl DaemonCommand

Source

pub fn new(program: impl AsRef<Path>) -> Self

A daemon running program, with no arguments and both outputs discarded.

Source

pub fn arg(&mut self, arg: impl Into<OsString>) -> &mut Self

Append one argument.

Source

pub fn args<I, S>(&mut self, args: I) -> &mut Self
where I: IntoIterator<Item = S>, S: Into<OsString>,

Append several arguments.

Source

pub fn env( &mut self, name: impl Into<OsString>, value: impl Into<OsString>, ) -> &mut Self

Set a variable in the child’s environment.

On Windows, where names are case-insensitive, a later change to path replaces Path. That match folds ASCII letters only.

Source

pub fn env_remove(&mut self, name: impl Into<OsString>) -> &mut Self

Remove a variable the child would otherwise inherit.

Source

pub fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self

Run the child in dir instead of the caller’s working directory.

Source

pub fn stdout(&mut self, target: DaemonOutput) -> &mut Self

Where stdout goes. Discarded by default.

Source

pub fn stderr(&mut self, target: DaemonOutput) -> &mut Self

Where stderr goes. Discarded by default.

Source

pub fn readiness_channel(&mut self) -> &mut Self

Give the daemon a readiness channel; DaemonChild::take_readiness returns the launcher’s end.

The daemon takes its end with Notifier::from_env, which finds it through the ENV variable. Without this call the daemon gets no channel, and ENV is removed from its environment in case the caller’s own has it.

On Unix the channel is a pipe. On macOS the standard library creates a pipe and then marks it close-on-exec, so a child that another thread spawns in between, other than through this crate, can inherit it and hide the daemon’s exit. The crate’s own spawns wait while the pipe is created, as they do for a listener; see local::unix_socket::acquire for what other spawns need. On Windows it is a named pipe the daemon opens by name, and the launcher also watches the daemon’s process, so a daemon that exits before it connects is reported at once.

use kunobi_daemon::launch::DaemonCommand;
use std::time::Duration;

let mut daemon = DaemonCommand::new("/usr/local/bin/exampled")
    .readiness_channel()
    .spawn()?;
let mut channel = daemon.take_readiness().expect("asked for above");
// Up to ten seconds between messages, however long the start takes.
if let Err(reason) = channel.wait(Duration::from_secs(10)) {
    let doing = channel.last_progress().unwrap_or_default();
    return Err(format!("{reason} (last progress: {doing:?})").into());
}
// Ready is the daemon's word: probe its endpoint before relying on it.
Source

pub fn spawn(&self) -> Result<DaemonChild>

Start the daemon.

Returns once the OS has created the process. Whether it goes on to serve is the caller’s liveness probe, as with spawn_and_wait.

Trait Implementations§

Source§

impl Debug for DaemonCommand

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl From<&Command> for DaemonCommand

The program, arguments, environment changes and working directory of command, as a daemon to start detached.

Nothing else carries over: not its stdio, which DaemonOutput sets, nor env_clear, which Command does not report, nor platform settings such as arg0, pre_exec or creation flags.

Source§

fn from(command: &Command) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.