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
impl DaemonCommand
Sourcepub fn new(program: impl AsRef<Path>) -> Self
pub fn new(program: impl AsRef<Path>) -> Self
A daemon running program, with no arguments and both outputs discarded.
Sourcepub fn env(
&mut self,
name: impl Into<OsString>,
value: impl Into<OsString>,
) -> &mut Self
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.
Sourcepub fn env_remove(&mut self, name: impl Into<OsString>) -> &mut Self
pub fn env_remove(&mut self, name: impl Into<OsString>) -> &mut Self
Remove a variable the child would otherwise inherit.
Sourcepub fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self
pub fn current_dir(&mut self, dir: impl AsRef<Path>) -> &mut Self
Run the child in dir instead of the caller’s working directory.
Sourcepub fn stdout(&mut self, target: DaemonOutput) -> &mut Self
pub fn stdout(&mut self, target: DaemonOutput) -> &mut Self
Where stdout goes. Discarded by default.
Sourcepub fn stderr(&mut self, target: DaemonOutput) -> &mut Self
pub fn stderr(&mut self, target: DaemonOutput) -> &mut Self
Where stderr goes. Discarded by default.
Sourcepub fn readiness_channel(&mut self) -> &mut Self
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.Sourcepub fn spawn(&self) -> Result<DaemonChild>
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
impl Debug for DaemonCommand
Source§impl From<&Command> for DaemonCommand
The program, arguments, environment changes and working directory of
command, as a daemon to start detached.
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.