Skip to content

fix: disable Rocket signal handling to prevent zombie process#276

Draft
lohrm-spf wants to merge 2 commits intoglzr-io:mainfrom
michidk:fix/disable-rocket-signal-handling
Draft

fix: disable Rocket signal handling to prevent zombie process#276
lohrm-spf wants to merge 2 commits intoglzr-io:mainfrom
michidk:fix/disable-rocket-signal-handling

Conversation

@lohrm-spf
Copy link
Copy Markdown

@lohrm-spf lohrm-spf commented Mar 20, 2026

Summary

  • Disables Rocket's built-in ctrlc and Unix signals shutdown triggers in the asset server configuration.
  • Fixes the single-instance handler to recreate widgets when re-launched after all windows were destroyed externally.

Problem

Zombie path 1: Rocket signal handling

Rocket 0.5 registers signal handlers (SIGTERM by default on Unix, SIGINT via ctrlc) that replace the OS defaults. When an external process manager (e.g. GlazeWM) sends SIGTERM to Zebar:

  1. Rocket catches SIGTERM and gracefully shuts down the HTTP asset server
  2. launch().await returns Ok(()) — no error is logged
  3. Tauri's event loop + placeholder window keep the process alive
  4. Zebar is now a zombie: running but without an asset server, so widgets cannot render
  5. The tauri-plugin-single-instance lock is still held by the zombie
  6. Any new zebar instance detects the lock, communicates with the zombie, and exits
  7. Result: no working Zebar, no way to start a new one without manually killing the zombie

Zombie path 2: External window destruction

When a window manager restarts (e.g. GlazeWM during development), it can destroy Zebar's widget windows externally. The placeholder window keeps the process alive, but widget_states is now empty. If the WM then re-launches zebar:

  1. New instance detects the single-instance lock
  2. CLI args forwarded to the existing instance as CliCommand::Empty
  3. The single-instance handler unconditionally no-ops for Empty
  4. Result: process alive with asset server running, but zero visible widgets and no way to recover without manually killing the process

Fix

Rocket signal handling

Disable Rocket's signal handling so SIGTERM/SIGINT fall through to the OS default (process termination). The asset server lifecycle is now tied to the process — when the process dies, everything dies, and the single-instance lock is released.

  • shutdown.ctrlc = false — Rocket won't intercept Ctrl-C
  • shutdown.signals = [] (Unix only) — Rocket won't intercept SIGTERM

Normal Tauri-initiated shutdown still works: when the Tauri event loop exits, the tokio runtime is dropped, cancelling the Rocket background task.

Single-instance widget recovery

The Empty command now only no-ops when widgets are still alive. If widget_states is empty, startup() is called to recreate widgets from the startup config.

Rocket 0.5 registers signal handlers for SIGTERM/SIGINT that replace the
OS defaults. When an external process (e.g. GlazeWM) sends SIGTERM to
Zebar, Rocket catches the signal and gracefully shuts down the HTTP
server — but the Tauri event loop keeps the process alive. This leaves a
zombie Zebar that holds the single-instance lock, preventing any new
instance from starting, while the asset server is no longer running so
widgets cannot render.

Disable Rocket's ctrlc and Unix signal triggers so that SIGTERM/SIGINT
fall through to the OS default (process termination).
@github-project-automation github-project-automation bot moved this to 📬 Needs triage in zebar Mar 20, 2026
When a window manager (e.g. GlazeWM) restarts, it can destroy Zebar's
widget windows externally. The placeholder window keeps the process
alive but widget_states is now empty. If the WM then re-launches
zebar, the single-instance handler received CliCommand::Empty and
unconditionally no-op'd — leaving the process running with zero
visible widgets.

Now the Empty command only no-ops when widgets are still alive.
If widget_states is empty, startup() is called to recreate them
from the startup config.
@lohrm-spf lohrm-spf marked this pull request as draft March 20, 2026 20:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 📬 Needs triage

Development

Successfully merging this pull request may close these issues.

2 participants