Add smol implementation for spawn

Although this is used in apps that use `tokio`, if we're going to
support `smol`, this seems suboptimal to require.

This assumes the function will be called by a tokio executor if the
`tokio` feature is used. Otherwise it can be spawned from any executor.
That should be consistent with everything else.

This fails to compile without either the `tokio` or `smol` feature. This
seems reasonable, since `zbus` also fails to compile in that case.
This commit is contained in:
Ian Douglas Scott 2024-07-26 10:56:19 -07:00 committed by Ian Douglas Scott
parent 8c00bf3d8b
commit 732c7aef5c
2 changed files with 23 additions and 6 deletions

View file

@ -1,8 +1,26 @@
#[cfg(all(feature = "smol", not(feature = "tokio")))]
use smol::io::AsyncReadExt;
use std::fs::File;
use std::io;
use std::os::fd::OwnedFd;
use std::process::{exit, Command, Stdio};
#[cfg(feature = "tokio")]
use tokio::io::AsyncReadExt;
#[cfg(feature = "tokio")]
async fn read_from_pipe(read: OwnedFd) -> Option<u32> {
let mut read = tokio::net::unix::pipe::Receiver::from_owned_fd(read).unwrap();
read.read_u32().await.ok()
}
#[cfg(all(feature = "smol", not(feature = "tokio")))]
async fn read_from_pipe(read: OwnedFd) -> Option<u32> {
let mut read = smol::Async::new(std::fs::File::from(read)).unwrap();
let mut bytes = [0; 4];
read.read_exact(&mut bytes).await.ok()?;
Some(u32::from_be_bytes(bytes))
}
/// Performs a double fork with setsid to spawn and detach a command.
pub async fn spawn(mut command: Command) -> Option<u32> {
command
@ -17,10 +35,9 @@ pub async fn spawn(mut command: Command) -> Option<u32> {
match unsafe { libc::fork() } {
// Parent process
1.. => {
// Drop copy of write end, then read PID from pipe
drop(write);
// Read PID from pipe
let mut read = tokio::net::unix::pipe::Receiver::from_owned_fd(read).unwrap();
read.read_u32().await.ok()
read_from_pipe(read).await
}
// Child process