#[cfg(unix)]
use std::fs::File;
#[cfg(unix)]
use std::path::Path;
use anyhow::{Context, Result};
use mcpmesh_trust::paths;
#[cfg(unix)]
use crate::ipc;
pub fn run() -> Result<()> {
#[cfg(unix)]
let _lock = {
let runtime = paths::runtime_dir()?;
ipc::ensure_runtime_dir(&runtime)?;
let lock_path = runtime.join("mcpmesh.lock");
match acquire_singleton_lock(&lock_path)? {
Some(lock) => lock,
None => {
tracing::info!("another mcpmesh daemon already holds the singleton lock; exiting");
return Ok(());
}
}
};
let socket = paths::default_endpoint()?;
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.context("build daemon tokio runtime")?;
rt.block_on(async move {
mcpmesh_node::daemon::serve_forever(&socket, mcpmesh_node::NodePaths::from_env()?).await
})
}
#[cfg(unix)]
fn acquire_singleton_lock(lock_path: &Path) -> Result<Option<File>> {
use rustix::fs::{FlockOperation, flock};
let file = std::fs::OpenOptions::new()
.create(true)
.read(true)
.write(true)
.truncate(false)
.open(lock_path)
.with_context(|| format!("open singleton lock {}", lock_path.display()))?;
match flock(&file, FlockOperation::NonBlockingLockExclusive) {
Ok(()) => Ok(Some(file)),
Err(rustix::io::Errno::WOULDBLOCK) => Ok(None),
Err(e) => Err(anyhow::Error::new(e).context("flock singleton lock")),
}
}