Compare commits

..

6 commits

Author SHA1 Message Date
Qyriad
420fac5f18 fix a bunch of lints 2026-03-22 17:10:26 +01:00
Qyriad
aed73e99be use lld for faster link times 2026-03-22 17:02:53 +01:00
Qyriad
88be53cd2f remove the persistent buffer until a refactor makes it per-connection 2026-03-22 17:02:53 +01:00
Qyriad
bd3ec3a904 nix: apply mkPretty to sub-derivations 2026-03-22 17:02:53 +01:00
Qyriad
e016c37634 customize Cargo a bit, for now 2026-03-22 16:41:01 +01:00
Qyriad
373e300b59 flake.lock: Update
Flake lock file updates:

• Updated input 'fenix':
    'github:nix-community/fenix/64407ddb1932af06ed5cd711f6a2ed946b2548b9' (2026-03-10)
  → 'github:nix-community/fenix/4cd28929c68cae521589bc21958d3793904ed1e2' (2026-03-22)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/608d0cadfed240589a7eea422407a547ad626a14' (2026-03-08)
  → 'github:NixOS/nixpkgs/9cf7092bdd603554bd8b63c216e8943cf9b12512' (2026-03-18)
2026-03-22 15:00:06 +01:00
11 changed files with 102 additions and 83 deletions

10
.cargo/config.toml Normal file
View file

@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: 2026 Qyriad <qyriad@qyriad.me>
#
# SPDX-License-Identifier: EUPL-1.1
# vim: tabstop=2 shiftwidth=0 noexpandtab
[build]
rustflags = [
"-C", "force-frame-pointers=yes",
"-C", "force-unwind-tables=yes",
]

View file

@ -47,3 +47,19 @@ tap = "1.0.1"
tracing = { version = "0.1.44", features = ["attributes"] }
tracing-human-layer = "0.2.1"
tracing-subscriber = { version = "0.3.22", default-features = false, features = ["std", "env-filter", "fmt", "ansi", "registry", "parking_lot"] }
[profile.dev]
opt-level = 1
lto = "thin"
[profile.release]
debug = true
debug-assertions = true
lto = true
[profile.dev.package."*"]
opt-level = 1
[profile.release.package."*"]
debug = true
debug-assertions = true

View file

@ -9,7 +9,11 @@
in import src { inherit pkgs; },
}: let
inherit (qpkgs) lib;
dynix = qpkgs.callPackage ./package.nix { }
dynix = (qpkgs.callPackage ./package.nix { })
.overrideAttrs (final: prev: {
dynixCommand = qpkgs.stdlib.mkStdenvPretty prev.dynixCommand;
dynixModules = qpkgs.stdlib.mkStdenvPretty prev.dynixModules;
})
|> qpkgs.stdlib.mkStdenvPretty;
byStdenv = lib.mapAttrs (stdenvName: stdenv: let
withStdenv = dynix.override { clangStdenv = stdenv; };

12
flake.lock generated
View file

@ -3,11 +3,11 @@
"fenix": {
"flake": false,
"locked": {
"lastModified": 1773126504,
"narHash": "sha256-/iXlg2V5UMlgCmyRHkPHjlD6NdMfFOnwFMvH7REigD4=",
"lastModified": 1774163246,
"narHash": "sha256-gzlqyLjP44LWraUd3Zn4xrQKOtK+zcBJ77pnsSUsxcM=",
"owner": "nix-community",
"repo": "fenix",
"rev": "64407ddb1932af06ed5cd711f6a2ed946b2548b9",
"rev": "4cd28929c68cae521589bc21958d3793904ed1e2",
"type": "github"
},
"original": {
@ -37,11 +37,11 @@
"nixpkgs": {
"flake": false,
"locked": {
"lastModified": 1772956932,
"narHash": "sha256-M0yS4AafhKxPPmOHGqIV0iKxgNO8bHDWdl1kOwGBwRY=",
"lastModified": 1773840656,
"narHash": "sha256-9tpvMGFteZnd3gRQZFlRCohVpqooygFuy9yjuyRL2C0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "608d0cadfed240589a7eea422407a547ad626a14",
"rev": "9cf7092bdd603554bd8b63c216e8943cf9b12512",
"type": "github"
},
"original": {

View file

@ -7,14 +7,23 @@
clangStdenv,
callPackage,
linkFarm,
llvmPackages,
rustHooks,
rustPackages,
versionCheckHook,
wrapBintoolsWith,
}: lib.callWith' rustPackages ({
rustPlatform,
cargo,
}: let
stdenv = clangStdenv;
# Use LLD for faster link times.
stdenv = clangStdenv.override {
cc = clangStdenv.cc.override {
bintools = wrapBintoolsWith {
bintools = llvmPackages.bintools;
};
};
};
cargoToml = lib.importTOML ./Cargo.toml;
cargoPackage = cargoToml.package;
in stdenv.mkDerivation (finalAttrs: let

View file

@ -21,7 +21,7 @@
inherit (pkgs) lib;
mkDevShell = dynix: qpkgs.callPackage dynix.mkDevShell { inherit fenixToolchain; };
devShell = mkDevShell dynix;
devShell = mkDevShell dynix |> qpkgs.stdlib.mkStdenvPretty;
byStdenv = lib.mapAttrs (lib.const mkDevShell) dynix.byStdenv;

View file

@ -1,5 +1,5 @@
use std::{
env, io, mem,
env, io,
ops::Deref,
os::fd::{AsFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd},
sync::{
@ -26,7 +26,7 @@ use crate::{
use crate::{OwnedFdWithFlags, TokenFd};
pub static UID: LazyLock<Uid> = LazyLock::new(|| rustix::process::getuid());
pub static UID: LazyLock<Uid> = LazyLock::new(rustix::process::getuid);
pub static USER_SOCKET_DIR: LazyLock<&'static Path> = LazyLock::new(|| {
let dir: Box<Path> = env::var_os("XDG_RUNTIME_DIR")
@ -52,19 +52,23 @@ pub enum ConvenientAttrPath {
}
impl ConvenientAttrPath {
/// Not currently used, but here for completeness.
#[expect(dead_code)]
pub fn clone_from_dotted(s: &str) -> Self {
Self::Dotted(Box::from(s))
}
/// Not currently used, but here for completeness.
#[expect(dead_code)]
pub fn clone_from_split(s: &[&str]) -> Self {
Self::from_str_iter(s.into_iter().map(Deref::deref))
Self::from_str_iter(s.iter().map(Deref::deref))
}
pub fn from_str_iter<'i, I>(iter: I) -> Self
where
I: Iterator<Item = &'i str>,
{
let boxed = iter.map(|s| Box::from(s));
let boxed = iter.map(Box::from);
Self::Split(Box::from_iter(boxed))
}
@ -135,9 +139,6 @@ pub struct Daemon {
// Bijective mapping of [`mio::Token`]s to [`RawFd`]s.
tokfd: BiHashMap<TokenFd>,
cmd_buffer: Vec<u8>,
next_timeout: Option<Duration>,
}
/// `tokfd` handling.
@ -222,6 +223,8 @@ impl Daemon {
.copied()
}
/// Not currently used, but here for completeness.
#[expect(dead_code)]
fn token_for_fd(&self, fd: RawFd) -> Option<Token> {
self.tokfd
.get2(&fd)
@ -255,10 +258,10 @@ impl Daemon {
debug!("opened daemon to {:?} file descriptor {fd:?}", name);
let path = match &name {
Some(name) => Some(PathBuf::from(name).into_boxed_path()),
None => None,
};
let path = name
.as_ref()
.map(PathBuf::from)
.map(PathBuf::into_boxed_path);
Self {
config_path,
@ -267,8 +270,6 @@ impl Daemon {
poller,
fd_info,
tokfd: Default::default(),
cmd_buffer: Vec::with_capacity(1024),
next_timeout: TIMEOUT_NEVER,
}
}
@ -345,16 +346,12 @@ impl Daemon {
/// Private helpers.
impl Daemon {
fn read_cmd(&mut self, fd: &BorrowedFd) -> Result<(), IoError> {
if self.cmd_buffer.len() == self.cmd_buffer.capacity() {
self.cmd_buffer.reserve(1024);
}
// FIXME: don't use a new allocation every time.
let mut cmd_buffer: Vec<u8> = Vec::with_capacity(1024);
let _count = rustix::io::read(fd, spare_capacity(&mut self.cmd_buffer))
let _count = rustix::io::read(fd, spare_capacity(&mut cmd_buffer))
.tap_err(|e| error!("read() on daemon fd {fd:?} failed: {e}"))?;
// So that the loop doesn't borrow from `self`.
let mut cmd_buffer = mem::take(&mut self.cmd_buffer);
// The buffer might have existing data from the last read.
let deserializer = serde_json::Deserializer::from_slice(&cmd_buffer);
let stream: StreamDeserializer<_, DaemonCmd> = deserializer.into_iter();
@ -362,16 +359,13 @@ impl Daemon {
let cmd = match cmd {
Ok(cmd) => cmd,
Err(e) if e.is_eof() => {
self.next_timeout = Some(Duration::from_secs(4));
warn!("Didn't get a valid daemon command; giving the other side 4 seconds...");
let _ = mem::replace(&mut self.cmd_buffer, cmd_buffer);
warn!("Got EOF before a valid command");
debug!("command buffer was: {:?}", cmd_buffer.as_bstr());
return Ok(());
},
Err(e) => {
warn!("error deserializing command: {e}");
debug!("command buffer was: {:?}", cmd_buffer.as_bstr());
cmd_buffer.clear();
let _ = mem::replace(&mut self.cmd_buffer, cmd_buffer);
// Don't propagate the error unless we have too many.
self.fd_error_push(fd.as_raw_fd(), e.into()).tap_err(|e| {
error!("Accumulated too many errors for daemon fd {fd:?}: {e}")
@ -385,9 +379,6 @@ impl Daemon {
self.dispatch_cmd(cmd).unwrap_or_else(|e| todo!("{e}"));
}
cmd_buffer.clear();
let _ = mem::replace(&mut self.cmd_buffer, cmd_buffer);
Ok(())
}
@ -469,25 +460,19 @@ impl Daemon {
}
}
if let Some(timeout) = self.next_timeout {
debug!(
"epoll_wait() with a timeout: {}",
humantime::format_duration(timeout),
);
}
match self.poller.poll(&mut events, self.next_timeout.take()) {
match self.poller.poll(&mut events, TIMEOUT_NEVER) {
Ok(_) => {
trace!(
"mio::Poller::poll() got events: {:?}",
events.iter().size_hint().0,
);
if events.is_empty() {
warn!("timeout expired");
self.cmd_buffer.clear();
} else {
let _ = self.fd_error_pop(self.poller.as_raw_fd());
unreachable!(
"epoll_wait() with a \"forever\" timeout should never give empty events",
);
}
let _ = self.fd_error_pop(self.poller.as_raw_fd());
},
Err(e) if e.kind() == IoErrorKind::Interrupted => {
// EINTR is silly.

View file

@ -130,7 +130,7 @@ impl From<OwnedFd> for OwnedFdWithFlags {
impl Read for &OwnedFdWithFlags {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, IoError> {
debug_assert!(buf.len() > 0);
debug_assert!(!buf.is_empty());
loop {
buf.fill(0);
match rustix::io::read(self.as_ref_owned(), &mut *buf) {

View file

@ -52,7 +52,7 @@ impl FdInfo {
match Self::guess_name(self.fd) {
Ok(name) => {
let prev = self.name.set(Box::from(name));
let prev = self.name.set(name);
debug_assert_eq!(prev, Ok(()));
},
Err(e) => {
@ -105,13 +105,14 @@ impl<'a> Display for FdInfoDisplay<'a> {
}
#[derive(Copy)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[non_exhaustive]
pub enum FdKind {
File,
Socket,
SockStream,
Poller,
#[default]
Unknown,
}
@ -128,12 +129,6 @@ impl FdKind {
}
}
impl Default for FdKind {
fn default() -> FdKind {
FdKind::Unknown
}
}
#[derive(Copy)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TokenFd {

View file

@ -14,7 +14,7 @@ use tracing_subscriber::{EnvFilter, layer::SubscriberExt};
fn main_wrapped() -> Result<(), Box<dyn StdError + Send + Sync + 'static>> {
// Default RUST_LOG to warn if it's not specified.
if let None = env::var_os("RUST_LOG") {
if env::var_os("RUST_LOG").is_none() {
unsafe {
env::set_var("RUST_LOG", "warn");
}

View file

@ -5,27 +5,27 @@
#[allow(unused_imports)]
use crate::prelude::*;
#[derive(Debug, Clone, PartialEq, Hash)]
pub(crate) struct NixEvalExpr<E, A> {
pub(crate) expr: E,
pub(crate) attrpath: A,
}
impl<E, A> NixEvalExpr<E, A>
where
E: AsRef<OsStr>,
A: AsRef<OsStr>,
{
pub(crate) fn into_command(self) -> Command {
let mut cmd = Command::new("nix-instantiate");
cmd.arg("--eval")
.arg("--json")
.arg("--strict")
.arg("--expr")
.arg(self.expr)
.arg("-A")
.arg(self.attrpath);
cmd
}
}
//#[derive(Debug, Clone, PartialEq, Hash)]
//pub(crate) struct NixEvalExpr<E, A> {
// pub(crate) expr: E,
// pub(crate) attrpath: A,
//}
//
//impl<E, A> NixEvalExpr<E, A>
//where
// E: AsRef<OsStr>,
// A: AsRef<OsStr>,
//{
// pub(crate) fn into_command(self) -> Command {
// let mut cmd = Command::new("nix-instantiate");
// cmd.arg("--eval")
// .arg("--json")
// .arg("--strict")
// .arg("--expr")
// .arg(self.expr)
// .arg("-A")
// .arg(self.attrpath);
//
// cmd
// }
//}