From 1326cd8c883ee084fa1e711d4e642eece50aac4c Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Fri, 11 Sep 2026 18:32:44 -0700 Subject: [PATCH 1/2] prometheus: remove stale unix socket file when binding from ffi --- src/core/config.rs | 28 ++++++++++++++++++++++++++++ src/core/prometheus.rs | 30 ++++++++++-------------------- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/core/config.rs b/src/core/config.rs index 460655c7e..90941e089 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -630,6 +630,34 @@ pub enum NetListenConfig { Unix(UnixListenConfig), } +impl NetListenConfig { + /// Parse config file prometheus_port format. + pub fn from_prometheus_port_str(s: &str) -> Result { + if let Some(path) = s.strip_prefix("ipc://") { + Ok(Self::Unix(UnixListenConfig { + path: path.into(), + mode: None, + user: None, + group: None, + params: HashMap::new(), + })) + } else { + let addr = if let Ok(addr) = s.parse::() { + addr + } else if let Ok(port) = s.parse::() { + std::net::SocketAddr::from(([0, 0, 0, 0], port)) + } else { + return Err(format!("invalid prometheus_port config: {s}")); + }; + + Ok(Self::Tcp(TcpListenConfig { + addr, + params: HashMap::new(), + })) + } + } +} + impl FromStr for NetListenConfig { type Err = String; diff --git a/src/core/prometheus.rs b/src/core/prometheus.rs index 3f5f375a1..e7db3430a 100644 --- a/src/core/prometheus.rs +++ b/src/core/prometheus.rs @@ -281,31 +281,13 @@ async fn handle_connection( pub mod ffi { use super::*; + use crate::core::config::NetListenConfig; use libc::c_char; use std::ffi::{CStr, CString}; /// Opaque handle to a `prometheus::Registry`, for use across the FFI boundary. pub enum PrometheusRegistry {} - fn parse_listen_addr(addr: &str) -> Result { - if let Some(path) = addr.strip_prefix("ipc://") { - let l = mio::net::UnixListener::bind(path) - .map_err(|e| format!("failed to bind {path}: {e}"))?; - Ok(NetListener::Unix(l)) - } else if let Ok(socket_addr) = addr.parse::() { - let l = mio::net::TcpListener::bind(socket_addr) - .map_err(|e| format!("failed to bind {socket_addr}: {e}"))?; - Ok(NetListener::Tcp(l)) - } else if let Ok(port) = addr.parse::() { - let socket_addr = std::net::SocketAddr::from(([0, 0, 0, 0], port)); - let l = mio::net::TcpListener::bind(socket_addr) - .map_err(|e| format!("failed to bind {socket_addr}: {e}"))?; - Ok(NetListener::Tcp(l)) - } else { - Err(format!("invalid listen address: {addr}")) - } - } - /// Create and start a prometheus HTTP server listening on `addr`. The provided `registry` is /// cloned internally so the server is independent of the registry's lifetime. Returns an opaque /// handle; call `prometheus_server_destroy` when done. On failure, returns null and writes a @@ -325,7 +307,15 @@ pub mod ffi { let addr = CStr::from_ptr(addr).to_str().expect("invalid addr string"); let registry = &*(registry as *const prometheus::Registry); - let listener = match parse_listen_addr(addr) { + let config = match NetListenConfig::from_prometheus_port_str(addr) { + Ok(c) => c, + Err(e) => { + *error = CString::new(e).unwrap_or_default().into_raw(); + return std::ptr::null_mut(); + } + }; + + let listener = match NetListener::bind_config(&config) { Ok(l) => l, Err(e) => { *error = CString::new(e).unwrap_or_default().into_raw(); From a8731f5aa906a68e5c577536f617b822ff6787bf Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Mon, 14 Sep 2026 11:49:29 -0700 Subject: [PATCH 2/2] address copilot feedback --- src/core/config.rs | 8 +++++++- src/core/prometheus.rs | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/core/config.rs b/src/core/config.rs index 90941e089..3a89b5b6d 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -634,6 +634,10 @@ impl NetListenConfig { /// Parse config file prometheus_port format. pub fn from_prometheus_port_str(s: &str) -> Result { if let Some(path) = s.strip_prefix("ipc://") { + if path.is_empty() { + return Err(format!("invalid listen address '{s}'; ipc path is empty")); + } + Ok(Self::Unix(UnixListenConfig { path: path.into(), mode: None, @@ -647,7 +651,9 @@ impl NetListenConfig { } else if let Ok(port) = s.parse::() { std::net::SocketAddr::from(([0, 0, 0, 0], port)) } else { - return Err(format!("invalid prometheus_port config: {s}")); + return Err(format!( + "invalid listen address '{s}'; expected ipc://PATH, IP:PORT, or PORT" + )); }; Ok(Self::Tcp(TcpListenConfig { diff --git a/src/core/prometheus.rs b/src/core/prometheus.rs index e7db3430a..387283039 100644 --- a/src/core/prometheus.rs +++ b/src/core/prometheus.rs @@ -304,7 +304,16 @@ pub mod ffi { registry: *const PrometheusRegistry, error: *mut *const c_char, ) -> *mut PrometheusServer { - let addr = CStr::from_ptr(addr).to_str().expect("invalid addr string"); + let addr = match CStr::from_ptr(addr).to_str() { + Ok(addr) => addr, + Err(e) => { + *error = CString::new(format!("invalid listen address: {e}")) + .unwrap_or_default() + .into_raw(); + return std::ptr::null_mut(); + } + }; + let registry = &*(registry as *const prometheus::Registry); let config = match NetListenConfig::from_prometheus_port_str(addr) {