Fix some documentation

This commit is contained in:
Mathieu Trossevin 2023-12-08 17:01:42 +01:00
parent 776be0c96a
commit 47f8d9c9bf
Signed by: mtrossevin
GPG key ID: D1DBB7EA828374E9
3 changed files with 50 additions and 22 deletions

View file

@ -1,3 +1,6 @@
//! Contains the error types used by the [`listen`](super) module.
#![allow(clippy::module_name_repetitions)]
use core::fmt::Display;
use core::num::ParseIntError;
use std::error::Error;
@ -7,7 +10,7 @@ use rustix::io::Errno;
use super::{FD_NAMES_VAR, FD_NUMBER_VAR, PID_VAR};
#[allow(clippy::module_name_repetitions)]
/// Errors that might happens when receiving file descriptors using [`FileDescriptor::receive()`](super::FileDescriptor::receive())
#[derive(Debug)]
pub enum ReceiveError {
/// The environement variable `LISTEN_PID` didn't exists (probably meaning that no file descriptor was passed to us).
@ -61,7 +64,7 @@ impl Error for ReceiveError {
}
}
#[allow(clippy::module_name_repetitions)]
/// Errors that might happens when receiving file descriptors along with their names using [`FileDescriptor::receive_with_names()`](super::FileDescriptor::receive_with_names()).
#[derive(Debug)]
pub enum ReceiveNameError {
/// The variable `LISTEN_FDNAMES` didn't exists.
@ -97,9 +100,10 @@ impl Error for ReceiveNameError {
}
}
#[allow(clippy::module_name_repetitions)]
/// Errors that might be obtained when producing the iterator in [`FileDescriptor::receive()`](super::FileDescriptor::receive())
#[derive(Debug)]
pub enum GetFdsError {
/// Too many file descriptors were passed so we overflowed when adding `SD_LISTEN_FDS_START` (3)
TooManyFDs(usize),
}
@ -113,11 +117,18 @@ impl Display for GetFdsError {
impl Error for GetFdsError {}
/// Errors when trying to duplicate the received file descriptors using [`rustix::fs::fcntl_dupfd_cloexec`].
#[derive(Debug)]
pub enum DupError {
/// The file descriptor we are attempting to duplicate isn't open.
InvalidFd(Errno),
/// Some other problem in the arguments passed to [`fcntl`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html).
InvalidArgument(Errno),
/// No file descriptor was available to us.
NoAvailableFd(Errno),
/// Some other error (see [`Errno`] and [`fcntl`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fcntl.html) for details).
///
/// Please fill a bug if you see this variant so that we might add a more precise variant.
Other(Errno),
}

View file

@ -1,3 +1,23 @@
//! Support for file descriptor passing with `LISTEN_FD`
//!
//! The entrypoints of this module are [`FileDescriptor::receive()`] and [`FileDescriptor::receive_with_names()`]. (And their **`unsafe`** `*_no_dup` variants.)
//!
//! ```no_run
//! # main() -> Result<(), Box<dyn std::error::Error>> {
//! let received_fd: Vec<FileDescriptor> = FileDescriptor::receive_with_names(true)
//! .into_iter()
//! .filter_map(|(name, res)| {
//! if name == "<expected_filename>" {
//! Some(res)
//! } else {
//! None
//! }
//! })
//! .collect()?
//! // Use the received file descriptors.
//! # Ok(())
//! # }
//! ```
use std::ffi::{OsStr, OsString};
use std::fs::File;
use std::net::{TcpListener, TcpStream, UdpSocket};
@ -20,10 +40,10 @@ const FD_NAMES_VAR: &str = "LISTEN_FDNAMES";
/// File Descriptor passed by systemd.
///
/// They are duplicated from the actual passed file descriptor so as to be safe to use from rust code.
/// They should truly be safe to use from rust code.
#[derive(Debug)]
pub enum FileDescriptor {
/// The file descriptor is a [`File`](std::fs::File).
/// The file descriptor is a [`File`].
///
/// If this is an FD provided by a .socket unit it corresponds to `ListenSpecial=`.
File(File),
@ -102,15 +122,15 @@ impl FileDescriptor {
///
/// The file descriptors are taken directly as [`OwnedFd`]s instead of being duplicated. In order to limit unsoundness this function therefore always unset the environment.
///
/// # Errors
///
/// This function will fail if no file descriptor colud be received which might not actually be an error. See [`ReceiveError`] for details.
///
/// # Safety
///
/// This function is safe if (and only if) the received file descriptors weren't already taken into a owned rust struct.
/// (In short it needs to follow the safety constraints of [`OwnedFd::from_raw_fd`](std::os::fd::FromRawFd)).
/// The simplest way to insure that it is so is to only use functions from this crate to get these file descriptors.
///
/// # Errors
///
/// This function will fail if no file descriptor colud be received which might not actually be an error. See [`ReceiveError`] for details.
pub unsafe fn receive_no_dup() -> Result<impl IntoIterator<Item = Self>, ReceiveError> {
let fds = Self::inner_receive(true)?;
@ -161,12 +181,11 @@ impl FileDescriptor {
/// This function will fail if no file descriptors could be obtained or the names associated with them couldn't be obtained. See [`ReceiveNameError`] for details.
pub fn receive_with_names(
unset_env: bool,
) -> Result<impl IntoIterator<Item = Result<(OsString, Self), DupError>>, ReceiveNameError>
) -> Result<impl IntoIterator<Item = (OsString, Result<Self, DupError>)>, ReceiveNameError>
{
let ret = Self::get_names()?
.into_iter()
.zip(Self::receive(unset_env)?)
.map(|(name, res)| res.map(|fd| (name, fd)));
.zip(Self::receive(unset_env)?);
Ok(ret)
}
@ -176,17 +195,15 @@ impl FileDescriptor {
///
/// The file descriptors are taken directly as [`OwnedFd`]s instead of being duplicated. In order to limit unsoundness this function therefore always unset the environment.
///
/// # Errors
///
/// This function will fail if no file descriptors could be obtained or the names associated with them couldn't be obtained. See [`ReceiveNameError`] for details.
///
/// # Safety
///
/// This function is safe if (and only if) the received file descriptors weren't already taken into a owned rust struct.
/// (In short it needs to follow the safety constraints of [`OwnedFd::from_raw_fd`](std::os::fd::FromRawFd)).
/// The simplest way to insure that it is so is to only use functions from this crate to get these file descriptors.
///
/// # Errors
///
/// This function will fail if no file descriptors could be obtained or the names associated with them couldn't be obtained. See [`ReceiveNameError`] for details.
///
///
pub unsafe fn receive_with_names_no_dup(
) -> Result<impl IntoIterator<Item = (OsString, Self)>, ReceiveNameError> {
let ret = Self::get_names()?.into_iter().zip(Self::receive_no_dup()?);

View file

@ -4,7 +4,7 @@
//!
//! # Example
//!
//! ```rust
//! ```no_run
//! # main() -> Result<(), Box<dyn std::error::Error>> {
//! // Do whatever you need for your service to be ready.
//! if let Some(notifier) = Notifier::new(true)? {
@ -78,7 +78,7 @@ impl Notifier {
/// Notify service manager about status change and send file descriptors.
///
/// Use this together with [`NotifyState::FdStore`]. Otherwise works like [`Notifier::notify`].
/// Use this together with [`NotifyState::FdStore`]. Otherwise works like [`Notifier::notify()`].
///
/// # Errors
///
@ -126,7 +126,7 @@ impl Notifier {
/// Notify service manager about status changes.
///
/// Send a notification to the manager about service status changes. Also see [`Notifier::notify_with_fds`] to send file descriptors.
/// Send a notification to the manager about service status changes. Also see [`Notifier::notify_with_fds()`] to send file descriptors.
///
/// # Errors
///
@ -145,7 +145,7 @@ pub enum NotifyState<'a> {
Errno(u8),
/// A name for the submitted file descriptors.
FdName(&'a str),
/// Stores additional file descriptors in the service manager. Use [`Notifier::notify_with_fds`] with this.
/// Stores additional file descriptors in the service manager. Use [`Notifier::notify_with_fds()`] with this.
FdStore,
/// Remove stored file descriptors. Must be used together with [`NotifyState::FdName`].
FdStoreRemove,