* fix(docker): reap orphan processes via tini + init, cap pids
The node runs as PID 1 in the container and never reaps reparented
orphans, so git grandchildren (e.g. pack-objects left behind when a
served clone disconnects) accumulate as zombies until fork() fails with
EAGAIN. Run under tini and set compose init: true so reparented orphans
are reaped, and add pids_limit as a blast-radius cap.
Refs #53
* fix(node): reap leaked git child processes (#53)
Serving git over smart-HTTP could leak zombie processes that, over weeks,
exhaust the PID table until fork() fails with EAGAIN and all git
operations break until restart.
The serve path (run_git_service) now runs git in its own process group and
SIGKILLs that group when the request future is dropped (client disconnect)
or returns early, so git and its pack-objects child are torn down together
instead of orphaning the grandchild to PID 1 as a zombie. A drop guard,
disarmed once the request completes cleanly, owns this teardown.
create_issue and build_filtered_pack spawned a std Child and dropped it
unwaited if the stdin write failed (and build_filtered_pack could panic on
a missing stdin handle). Both now always wait the child before surfacing
any error, so the failure path cannot leak.
Adds libc for the group-kill syscall and three regression tests covering
direct-child kill, grandchild reaping via the group, and the disarmed
no-kill path.
Refs #53
* fix(review): reap-then-disarm on serve-path errors; tini/comment nits
Address code-review findings on the #53 fix:
- run_git_service no longer early-returns on a stdin-write error. It captures
the write result, always reaps the child, then disarms the group guard
before surfacing the error. Previously a write/wait error path could drop
the still-armed guard after the child was already reaped, so the group
SIGKILL could in theory land on a reused pgid. (correctness, reliability,
adversarial all flagged this region.)
- Drop tini's -g flag: the node manages its own children and graceful
shutdown, so group-wide signalling would only disturb in-flight git helpers
on shutdown.
- Correct the SAFETY comment (kill(2) is not relevant to async-signal-safety
here) and the alive() test-helper comment (EPERM does not read as alive).
* fix(node): SIGTERM (not SIGKILL) the served-git group on disconnect
SIGKILL gave git no chance to run its signal cleanup, so an aborted
receive-pack could leave a stale .git/*.lock that blocks the next push.
SIGTERM lets git remove its lock files before exiting. Signalling the
whole process group still reaches pack-objects directly, so the grandchild
is terminated rather than orphaned, and a single immediate signal avoids
any delayed-kill pid-reuse window.
Refs #53
* docs(node): correct stale SIGKILL comments to SIGTERM in served-git teardown
- Menu bar icon with colored status dot (green/yellow/red)
- Start/Stop node via Docker Compose
- Settings UI: ports, public URL, postgres password, auto-sync, operator config
- View Logs window with live docker compose logs
- Auto-start on launch and login (SMAppService)
- Docker detection with install prompt
- Repo root detection via compile-time path for local builds
- Port variables wired through docker-compose.yml for custom port support
- GITLAWB_AUTO_SYNC passthrough for peer replication toggle
- Build script: scripts/build-macos-app.sh (codesign + DMG)
Co-authored-by: Rimas Mocevicius <[email protected]>
Touch alone wasn't enough — cargo can still reuse cached fingerprint
state from the dependency-cache layer. Explicitly remove the dummy
binaries and their fingerprint dirs so the second build reproduces
real artifacts unconditionally.
Also drop the obsolete `version: '3.9'` from docker-compose.yml.
Co-Authored-By: OpenClaude <[email protected]>