Skip to content

Commit

Permalink
fix: wait for activation before doing things
Browse files Browse the repository at this point in the history
  • Loading branch information
K900 committed Oct 5, 2022
1 parent ae7bca7 commit ac0c038
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 17 deletions.
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

devShell = pkgs.mkShell {
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
RUSTC_BOOTSTRAP = "1";

nativeBuildInputs = with pkgs; [
nixpkgs-fmt
Expand Down
2 changes: 2 additions & 0 deletions scripts/native-systemd-shim/shim.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ rustPlatform.buildRustPackage {

src = ./.;
cargoLock.lockFile = ./Cargo.lock;

RUSTC_BOOTSTRAP = "1";
}
33 changes: 16 additions & 17 deletions scripts/native-systemd-shim/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#![feature(linux_pidfd)]

use anyhow::Context;
use nix::mount::{mount, MsFlags};
use nix::unistd::execv;
use nix::sys::wait::{waitid, Id, WaitPidFlag};
use std::env;
use std::ffi::CString;
use std::fs::OpenOptions;
use std::os::unix::ffi::OsStrExt;
use std::os::linux::process::{ChildExt, CommandExt};
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::os::unix::process::CommandExt as _;
use std::process::{Command, Stdio};

fn real_main() -> anyhow::Result<()> {
Expand Down Expand Up @@ -37,30 +39,27 @@ fn real_main() -> anyhow::Result<()> {
.context("When opening /dev/kmsg")?
.into_raw_fd();

Command::new("/nix/var/nix/profiles/system/activate")
let mut child = Command::new("/nix/var/nix/profiles/system/activate")
.env("LANG", "C.UTF-8")
// SAFETY: we just opened this
.stdout(unsafe { Stdio::from_raw_fd(kmsg_fd) })
.stderr(unsafe { Stdio::from_raw_fd(kmsg_fd) })
.create_pidfd(true)
.spawn()
.context("When activating")?;

log::trace!("Spawning real systemd...");
let pidfd = child.take_pidfd().context("When getting pidfd")?;
waitid(Id::PIDFd(pidfd.into_raw_fd()), WaitPidFlag::WEXITED).context("When waiting")?;

let args = env::args_os()
.map(|x| CString::new(x.as_bytes()))
.collect::<Result<Vec<_>, _>>()
.context("When preparing systemd arguments")?;
log::trace!("Spawning real systemd...");

execv(
CString::new("/nix/var/nix/profiles/system/systemd/lib/systemd/systemd")?.as_c_str(),
&args,
// if things go right, we will never return from here
Err(
Command::new("/nix/var/nix/profiles/system/systemd/lib/systemd/systemd")
.args(env::args_os())
.exec()
.into(),
)
.context("When spawning systemd")?;

// this should never be reached, but the ! type is experimental
// so we can't just return that
Ok(())
}

fn main() {
Expand Down

0 comments on commit ac0c038

Please sign in to comment.