Skip to content

Commit da04f7c

Browse files
danielkovclaude
andcommitted
fix: Windows build errors in daemon and CLI
- Add Windows support to granaryd.rs with named pipes and Ctrl+C handling - Move Stdio import inside #[cfg(unix)] block in auto_start.rs - Add #[cfg_attr] to suppress unused variable warnings on Windows in run.rs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 80b1c82 commit da04f7c

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

src/bin/granaryd.rs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::sync::Arc;
2121
use std::time::Duration;
2222

2323
use tokio::select;
24+
#[cfg(unix)]
2425
use tokio::signal::unix::{SignalKind, signal};
2526
use tracing_appender::non_blocking::WorkerGuard;
2627

@@ -66,13 +67,27 @@ async fn main() -> anyhow::Result<()> {
6667
}
6768

6869
// Start IPC listener
69-
let socket_path = global_config_service::daemon_socket_path()?;
70-
let listener = IpcListener::bind(&socket_path).await?;
70+
#[cfg(unix)]
71+
#[allow(unused_mut)] // Windows needs mut for accept(), Unix doesn't
72+
let mut listener = {
73+
let socket_path = global_config_service::daemon_socket_path()?;
74+
let listener = IpcListener::bind(&socket_path).await?;
75+
tracing::info!("granaryd listening on {:?}", listener.socket_path());
76+
listener
77+
};
7178

72-
tracing::info!("granaryd listening on {:?}", listener.socket_path());
79+
#[cfg(windows)]
80+
let mut listener = {
81+
let pipe_name = global_config_service::daemon_pipe_name();
82+
let listener = IpcListener::bind(&pipe_name).await?;
83+
tracing::info!("granaryd listening on {}", listener.pipe_name());
84+
listener
85+
};
7386

7487
// Set up signal handlers
88+
#[cfg(unix)]
7589
let mut sigterm = signal(SignalKind::terminate())?;
90+
#[cfg(unix)]
7691
let mut sigint = signal(SignalKind::interrupt())?;
7792

7893
// Flag to track shutdown request from IPC
@@ -95,7 +110,8 @@ async fn main() -> anyhow::Result<()> {
95110
_ => {}
96111
}
97112

98-
// Main loop
113+
// Main loop - Unix version with SIGTERM/SIGINT handling
114+
#[cfg(unix)]
99115
loop {
100116
// Check if shutdown was requested via IPC
101117
if shutdown_flag.load(std::sync::atomic::Ordering::SeqCst) {
@@ -147,6 +163,55 @@ async fn main() -> anyhow::Result<()> {
147163
}
148164
}
149165

166+
// Main loop - Windows version with Ctrl+C handling
167+
#[cfg(windows)]
168+
loop {
169+
// Check if shutdown was requested via IPC
170+
if shutdown_flag.load(std::sync::atomic::Ordering::SeqCst) {
171+
tracing::info!("Shutdown requested via IPC");
172+
break;
173+
}
174+
175+
select! {
176+
// Handle Ctrl+C
177+
_ = tokio::signal::ctrl_c() => {
178+
tracing::info!("Received Ctrl+C, shutting down...");
179+
break;
180+
}
181+
182+
// Periodic log cleanup
183+
_ = cleanup_interval.tick() => {
184+
match manager.cleanup_old_logs(&log_retention_config) {
185+
Ok(deleted) if deleted > 0 => {
186+
tracing::info!("Periodic log cleanup: deleted {} old log files", deleted);
187+
}
188+
Err(e) => {
189+
tracing::warn!("Periodic log cleanup failed: {}", e);
190+
}
191+
_ => {}
192+
}
193+
}
194+
195+
// Accept new connections
196+
result = listener.accept() => {
197+
match result {
198+
Ok(conn) => {
199+
let manager = Arc::clone(&manager);
200+
let shutdown_flag = Arc::clone(&shutdown_flag);
201+
tokio::spawn(async move {
202+
if let Err(e) = handle_connection(conn, &manager, &shutdown_flag).await {
203+
tracing::error!("Connection error: {}", e);
204+
}
205+
});
206+
}
207+
Err(e) => {
208+
tracing::error!("Accept error: {}", e);
209+
}
210+
}
211+
}
212+
}
213+
}
214+
150215
// Graceful shutdown
151216
tracing::info!("Shutting down workers...");
152217
manager.shutdown_all().await?;

src/cli/run.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ enum Signal {
378378
}
379379

380380
/// Check if a process is alive by using kill -0
381+
#[cfg_attr(not(unix), allow(unused_variables))]
381382
fn is_process_alive(pid: u32) -> bool {
382383
#[cfg(unix)]
383384
{
@@ -397,6 +398,7 @@ fn is_process_alive(pid: u32) -> bool {
397398
}
398399

399400
/// Send a signal to a process
401+
#[cfg_attr(not(unix), allow(unused_variables))]
400402
fn send_signal(pid: u32, signal: Signal) {
401403
#[cfg(unix)]
402404
{

src/daemon/auto_start.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! commands need it. It handles automatic daemon startup with exponential
55
//! backoff retry logic.
66
7-
use std::process::{Command, Stdio};
7+
use std::process::Command;
88
use std::time::Duration;
99
use tokio::time::sleep;
1010

@@ -69,6 +69,8 @@ pub async fn ensure_daemon() -> Result<DaemonClient> {
6969
/// sets up its own logging to `~/.granary/daemon/daemon.log`.
7070
#[cfg(unix)]
7171
fn spawn_daemon() -> Result<()> {
72+
use std::process::Stdio;
73+
7274
// Find the granaryd binary - it should be next to the granary binary
7375
let current_exe = std::env::current_exe()?;
7476
let daemon_path = current_exe.with_file_name("granaryd");

0 commit comments

Comments
 (0)