From 0834c21607ed3679f262b6f951c15e068ec7052e Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Wed, 20 May 2026 14:00:49 +0300 Subject: [PATCH] udev-shim: Harden rules file write with retry loop Handle BrokenPipe and AlreadyExists races when writing default udev rules during early boot. Retry up to 3 times with 50ms backoff. --- .../system/udev-shim/source/src/naming.rs | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/local/recipes/system/udev-shim/source/src/naming.rs b/local/recipes/system/udev-shim/source/src/naming.rs index ea1d36f15e..67509e4b55 100644 --- a/local/recipes/system/udev-shim/source/src/naming.rs +++ b/local/recipes/system/udev-shim/source/src/naming.rs @@ -2,6 +2,8 @@ use std::fs; use std::io; use std::os::unix::fs::symlink; use std::path::Path; +use std::thread; +use std::time::Duration; const DEFAULT_UDEV_RULES: &str = r#"# Network interface naming SUBSYSTEM=="net", KERNEL=="enp*", NAME="$kernel" @@ -74,8 +76,26 @@ pub fn write_default_rules_file() -> io::Result<&'static str> { fs::create_dir_all(dir)?; let path = dir.join("50-default.rules"); - fs::write(&path, default_udev_rules())?; - Ok("/etc/udev/rules.d/50-default.rules") + let contents = default_udev_rules(); + + if fs::metadata(&path).is_ok() { + let _ = fs::remove_file(&path); + } + + for attempt in 0..3 { + match fs::write(&path, contents) { + Ok(()) => return Ok("/etc/udev/rules.d/50-default.rules"), + Err(e) if e.kind() == io::ErrorKind::BrokenPipe && attempt < 2 => { + thread::sleep(Duration::from_millis(50)); + } + Err(e) if e.kind() == io::ErrorKind::AlreadyExists => { + return Ok("/etc/udev/rules.d/50-default.rules"); + } + Err(e) => return Err(e), + } + } + + unreachable!("write_default_rules_file loop always returns or errors") } fn parse_hex_byte(value: &str) -> Option {