Skip to content

main: add -F flag to stay in foreground#12

Merged
abonforti merged 1 commit intoazzurra:masterfrom
vjt:feat/foreground-flag
Apr 21, 2026
Merged

main: add -F flag to stay in foreground#12
abonforti merged 1 commit intoazzurra:masterfrom
vjt:feat/foreground-flag

Conversation

@vjt
Copy link
Copy Markdown
Contributor

@vjt vjt commented Apr 20, 2026

Summary

initialize() forks unconditionally at startup and exits the parent, which breaks every supervisor that needs the services process to remain on PID 1:

  • docker run ... — the container exits cleanly (0) the moment Running in background (pid: N) is printed, because the docker-visible process (the parent) has exit(EXIT_SUCCESS)'d. The daemonised child keeps running but is an orphan nobody's watching.
  • systemd units with Type=simple — same issue. Either you switch to Type=forking with a PIDFile= knob (and we write data/services.pid after fork, so ordering is racy) or the unit flips between activating and inactive.
  • tini / dumb-init / any PID-1 wrapper — defeated for the same reason.

This PR adds -F to make services skip the fork and run in the foreground. Without -F behaviour is bit-for-bit identical to today.

What changed

  • src/main.c — one file, +38/-7.
  • New file-static BOOL foreground = FALSE; near the other locals.
  • main(): after the argv[0] path fix, a trivial argv loop that sets foreground = TRUE on -F and prints a one-line usage for anything else.
  • initialize(): the fork() / exit(EXIT_SUCCESS) block is gated on !foreground. In foreground mode we print Running in foreground (pid: N) for parity with the old background-pid banner. Everything after (setpgid, write_pidfile, signal handlers, main loop) is untouched.

Why this shape

  • Minimal-surface change: no new file, no header changes, no build system touch. If -F is never passed, the diff is functionally dead code.
  • No getopt() pull-in just to handle one flag. Matches the existing ad-hoc style in main() (the argv[0] / chdir(dirname) block above).
  • Banner text follows the existing Running in background (pid: %d) wording so log scrapers that look for it still work.

Test plan

  • Clean build: ./configure && cd lang && python3 langcomp.py && cd .. && makegcc -Wall -Wshadow -Wcast-align -Wsign-compare, 0 warnings.
  • ./services -F in run/ works as before (no fork, startup continues up to the conf-file stage under the caller's tty).
  • ./services (no flag) still forks and exits parent immediately, unchanged behaviour.
  • Full stack bring-up under docker — this PR is a pre-req for azzurra/infra#2's testnet smoke, which needs the services container to stay on PID 1. Will verify once this is merged and SERVICES_REF in the infra Dockerfile points at a commit that includes this.

🤖 Generated with Claude Code

The fork() at initialize() time detaches services from its launcher and
exits the parent, which breaks every process supervisor (docker, systemd
with Type=simple, tini, ...) that expects the main process to remain on
PID 1 and receive signals directly. With -F set, main() parses the flag
before initialize() runs and the fork block in initialize() is skipped;
stdin/out/err stay wired to whatever the supervisor attached, and signals
land on the services process itself instead of being lost to the gone
parent.

Everything else (setpgid, pidfile write, signal handlers) runs exactly
as before — the only behavioural difference is that services doesn't
daemonize. Without -F the old behaviour is preserved bit-for-bit.

Build clean: gcc -Wall -Wshadow -Wcast-align -Wsign-compare, 0 warnings.
vjt added a commit to vjt/azzurra-testnet that referenced this pull request Apr 20, 2026
azzurra/services main.c unconditionally fork()s and exits the parent in
initialize() — under docker the container then sees PID 1 exit and
tears the whole stack down.

Upstream azzurra/services PR azzurra/services#12 adds a `-F` flag that
skips the fork and lets the process run as PID 1. This commit wires it
in; the testnet workflow will go green once #12 lands and a new
services image is pushed to GHCR.
@abonforti abonforti self-requested a review April 21, 2026 06:20
@abonforti abonforti merged commit 96300ee into azzurra:master Apr 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants