Skip to content

RELIABILITY: No Graceful Shutdown #33

@devfire

Description

@devfire

Severity: MEDIUM

Location

src/app.rs:94-100

Issue

Application just exits when stdin closes, with no cleanup:

tokio::select! {
    _ = udp_intake_handle => debug!("UDP intake task completed unexpectedly."),
    _ = display_handle => debug!("Display task completed unexpectedly."),
    _ = command_handle => debug!("Command task completed unexpectedly."),
    _ = message_handle => debug!("Message task completed unexpectedly."),
    _ = stdin_handle => debug!("Stdin task complete. Shutting down."),
}
// Just exits - no cleanup!

Problems

  1. No state persistence: Groups and keys lost
  2. No actor cleanup: Actors don't get shutdown signal
  3. Network not closed: UDP socket left open
  4. No graceful exit: Just terminates
  5. No goodbye messages: Other users don't know we left

What Should Happen

Phase 1: Signal shutdown

// Create shutdown signal
let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel(1);

// On exit
debug!("Initiating graceful shutdown...");
shutdown_tx.send(()).ok();

Phase 2: Save state

// Persist groups and key packages
state_actor.ask(SaveStateMsg).await?;

Phase 3: Send leave messages

// Notify other users we're leaving
for group_name in groups {
    send_leave_message(group_name).await?;
}

Phase 4: Clean up resources

// Close network
network_manager.shutdown().await?;

// Stop actors
state_actor.stop().await?;
identity_actor.stop().await?;

Phase 5: Wait for completion

// Give tasks time to finish
tokio::time::timeout(
    Duration::from_secs(5),
    join_all(handles)
).await?;

Full Example

pub async fn run(&mut self) -> Result<()> {
    // ... spawn tasks ...
    
    let (shutdown_tx, mut shutdown_rx) = broadcast::channel(1);
    
    tokio::select! {
        _ = stdin_handle => {
            info!("User initiated shutdown");
            shutdown_tx.send(()).ok();
        }
        _ = signal::ctrl_c() => {
            info!("Received CTRL-C");
            shutdown_tx.send(()).ok();
        }
    }
    
    // Graceful shutdown sequence
    self.shutdown(&state_actor, &network_manager).await?;
    
    Ok(())
}

Benefits

  • No data loss
  • Clean resource cleanup
  • Better user experience
  • Proper multi-user behavior
  • Can recover from crashes

Labels

reliability, enhancement, lifecycle

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions