subc-os 0.1.4

Operating-system primitives for the subc daemon that need unsafe code, behind a safe API: per-process identity, signalling, memory and CPU usage, and the launch-nonce descriptor handoff.
Documentation

Operating-system primitives the subc daemon needs and cannot reach without unsafe code, each behind a small safe API.

The daemon crates forbid unsafe code. This crate is the one deliberate exception (like subc-uptime and subc-cgroup): every unsafe block here is a single foreign call with its preconditions stated beside it, and nothing unsafe is exported.

Today it answers one question: is the process now holding pid N the same process the daemon spawned earlier? A pid alone cannot say, because the kernel reuses pids once a process has been reaped. [Process] reads the two facts that tell processes apart, the kernel's start time for the pid and the file identity (device and inode) of the executable image it runs, and sends signals to it.

Sources, per platform:

  • Linux: the start time is field 22 of /proc/<pid>/stat (clock ticks since boot), and the executable is stat through /proc/<pid>/exe, which resolves to the running image even if its file has since been replaced or deleted. A pidfd is opened before either is read and signals go through it (pidfd_send_signal), so the process that was checked is the process that is signalled. No unsafe code is needed: rustix wraps both calls.
  • macOS: the start time is kp_proc.p_starttime from sysctl KERN_PROC_PID (microseconds since the epoch), and the executable is the path proc_pidpath reports, then stat on that path. These two calls are the crate's only unsafe code. macOS has no pidfd, so a signal is a plain kill sent right after the checks; see [Process::signal].
  • Anywhere else: [Process::open] reports [std::io::ErrorKind::Unsupported].

It also reads how much memory and CPU time one process is using, for reporting only; see [resource_usage]. On Linux that is procfs again; on macOS it is proc_pid_rusage, plus mach_timebase_info to convert its CPU times to nanoseconds, the other two unsafe calls in the crate.

And it carries the launch nonce from the daemon to each module it spawns over an inherited pipe instead of the environment: [launch_nonce] is the one reader every module uses, and [LaunchNonceHandoff] the daemon's half. That module's unsafe code is dup2, fcntl, fstat and ioctl on descriptors, each with its preconditions stated beside it.