Skip to content

SingleInstance: secondary launch deletes the primary's socket; listener can hang on a silent client #79

Description

@rezdm

Problem

`SingleInstance::~SingleInstance()` (src/core/services/single_instance.cpp:52-54) unconditionally `unlink()`s the socket path on destruction, even when this instance never bound/listened on it.

Sequence:

  1. First launch binds the socket and becomes primary.
  2. Second launch connects, sends RAISE, and exits — its `SingleInstance` object still had `socket_path_` set (computed by `get_socket_path()` regardless of role) but `server_fd_` stayed -1.
  3. Its destructor unlinks the socket file anyway, deleting the first instance's live listening socket from the filesystem.
  4. A third launch's `connect()` now fails (file gone) and it becomes a second primary — single-instance is silently broken after any second launch.

Secondary issue

`listen_thread()` does a blocking `read()` on every accepted connection with no timeout. A client that connects but never writes (or never closes) wedges the listener thread; `~SingleInstance()`'s `join()` would then hang.

Fix

  • Track whether this object successfully bound+listened (e.g. `bool owns_socket_`); only unlink if true.
  • Bound the per-connection read (timeout via `SO_RCVTIMEO` or a poll/select with timeout) so a silent/malicious-ish client can't wedge the thread.

Found via code-review of user feedback after real-world macOS usage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions