ITADN

Main daemon socket is unavailable until expensive startup finishes

#2772Openchindris-mihai-alexandru 创建于 2026-04-01
# Issue draft: main daemon socket can remain unavailable for a long time during startup ## Title Main daemon socket is unavailable until expensive startup finishes, causing `failed to connect to socket` even while the daemon process is alive ## Body Hi, I dug into a Tahoe-era `failed to connect to socket` / “process alive but daemon unusable” case on my machine and found that at least one major class of these reports is a startup critical-path problem rather than an immediate socket/listener failure. ## Environment - macOS 26.4 Tahoe (`25E246`) - Apple Silicon - yabai `v7.1.18` - many apps/windows open across multiple displays ## Related issues / context - `#2535` — `failed to connect to socket` - `#2555` — debug output shows startup deep in `window_manager_begin(..)` while socket/connect failures are reported - `#2560` — daemon becomes unresponsive - `#2676` / `#2706` — Tahoe `failed to connect to socket` - `#2377` — responsiveness issues when some applications are slow/frozen - `#2595` — app observation can fail or stall randomly - `#439` — `kAXErrorCannotComplete` / problematic AX observation cases ## What I observed locally With a source build of `v7.1.18`, starting yabai in the foreground on a machine with many apps open: ```bash ./bin/yabai -V -c /dev/null ``` Before patching: - the process starts and stays alive - `/tmp/yabai_$USER.lock` appears quickly - `/tmp/yabai_$USER.socket` may not appear for a long time (I observed >25s) - `yabai -m query --displays` fails with `failed to connect to socket` So the user-visible symptom looks like “daemon alive, socket dead”, but in this case the daemon simply does not expose the main socket until very late in startup. ## Likely reason `message_loop_begin(g_socket_file)` happens after a long startup sequence, including: - process manager startup - display manager startup - window manager initialization / enumeration - existing application/window discovery On a busy machine, that path can take a long time. After instrumenting startup locally, `window_manager_begin(..)` was the major blocker. Example observations from my system: - `Google Drive` took ~7s - `LinkedIn Learning` took ~7s - several other apps took ~1–2s - total time before “ready” could exceed 20–45s ## Proposed fix Expose the message socket earlier in startup, before expensive application/window discovery finishes, and gate command handling until the daemon is ready. Concretely: 1. start `message_loop_begin(g_socket_file)` immediately after `event_loop_begin(..)` 2. keep a `g_daemon_is_ready` flag 3. if a client connects before startup is complete, return a clean failure response such as: - `daemon is still initializing; retry shortly.` This changes the user-visible behavior from: - `failed to connect to socket` to: - reachable daemon with deterministic “still initializing” response ## Local result After applying that change: - `/tmp/yabai_$USER.socket` appears within a few seconds on my machine (typically ~2–3s in repeated short runs) - early `yabai -m query --displays` no longer fails to connect once the socket is present - it returns `daemon is still initializing; retry shortly.` instead This does **not** solve the deeper slow-startup cause by itself, but it makes the daemon much more truthful, debuggable, and usable while startup is still in progress. ## Patch / PR I prepared a patch locally and can open a PR if this approach makes sense upstream. I can also post a follow-up issue specifically about the heavy `window_manager_begin(..)` critical path if that would be preferable.
1 条评论