agentsclimarketplace

Process lifecycle

Skill matejformanek/postgres-claude/.claude/skills/process-lifecycle

Turn Claude Code into a long-term collaborator on PostgreSQL internals — cited knowledge corpus, agent skills, slash commands, and task-shaped scenarios for backend hacking.

Install
npx -y skills add matejformanek/postgres-claude --skill process-lifecycle

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

PostgreSQL's per-connection multi-process model — postmaster fork, backend startup / initialization / query loop / clean shutdown, auxiliary processes (checkpointer, bgwriter, walwriter, autovacuum launcher, WAL summarizer, pgarch), background workers (bgworker.c registry + parallel/logical-rep workers), signal handling, and the FATAL/ERROR/PANIC hierarchy. Loads when the user asks about how a connection becomes a backend, what runs before the first query, why a query dies mid-flight, how signals + ProcessInterrupts + CHECK_FOR_INTERRUPTS work together, how autovacuum / bgworker workers get scheduled, or when planning a feature that hooks a startup phase / adds a new auxiliary process / touches shutdown ordering. Skip when the question is about client-side (libpq, drivers) or about the SQL-level session properties (that's `tcop` for query dispatch, `gucs-config` for GUCs).

SKILL.md

11.1 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

process-lifecycle — postmaster, backends, aux processes, bgworkers

PostgreSQL uses a per-connection process model, not threads. Every client connection gets its own OS process, forked from the postmaster. New backends do NOT inherit query state — every connection starts fresh through InitPostgres. This model shapes almost every feature.

The five process classes

ClassFilesLifetimeExample
Postmasterpostmaster/postmaster.c, pmchild.c, launch_backend.c, fork_process.cCluster-lifetimeThe parent process — accepts connections, forks children, reaps exits, restarts on crash.
Regular backendtcop/postgres.c, tcop/backend_startup.cConnection-lifetimeThe child that runs SQL for one client.
Auxiliary processpostmaster/auxprocess.c + one file each: checkpointer.c, bgwriter.c, walwriter.c, walsummarizer.c, startup.c, pgarch.c, syslogger.c, interrupt.cCluster-lifetimeAlways-on infrastructure processes; not for user queries.
Bgworkerpostmaster/bgworker.c + registered by extensionsConfigurable (per session / for lifetime of cluster / restart on crash)Autovacuum workers, parallel query workers, logical-rep apply workers, extension workers.
Autovacuum launcher/workerpostmaster/autovacuum.cCluster-lifetime launcher + short-lived workersSpecial case: launcher is aux, workers are bgworkers.

Backend lifecycle (regular query-serving backend)

Every incoming connection follows this sequence:

  1. Postmaster acceptspostmaster.c ServerLoop sees a new socket, calls BackendStartup in launch_backend.c.
  2. Fork or exec-and-fork — On Unix, fork() copies the postmaster into a child. On Windows or EXEC_BACKEND builds, the child re-execs and re-attaches to shmem via SubPostmasterMain.
  3. Auth handshakebackend_startup.c runs the startup message exchange, TLS/GSS, SCRAM/MD5/etc. authentication. Fails here → child exits before any query state exists.
  4. InitPostgres — This is the big one (in utils/init/postinit.c). Loads GUC per-role/per-db settings, opens the database's relcache/syscache, checks CONNECT permission, runs the login _PG_init hooks, ends up in PostgresMain.
  5. PostgresMain loop — the SQL query loop (in tcop/postgres.c). ReadCommand → exec → send RowDescription/DataRow/CommandComplete → ReadyForQuery → next iteration.
  6. Shutdown — Client sends X (Terminate), or postmaster signals shutdown, or fatal error. proc_exit runs registered callbacks (see on_shmem_exit / on_proc_exit in storage/ipc/ipc.c), releases locks + LWLocks, detaches from shmem.

The interrupt / signal system

Because backends can be interrupted between statements (query cancel, admin shutdown, sighup, deadlock), there's a specific pattern:

  • Signal handlers must be async-signal-safe. They set flags (InterruptPending, QueryCancelPending, ProcDiePending, ConfigReloadPending) and set the process latch (SetLatch(MyLatch)).
  • CHECK_FOR_INTERRUPTS() — macros sprinkled through the code that check the flags at safe points and call ProcessInterrupts (in tcop/postgres.c) if any are set.
  • ProcessInterrupts — the actual interrupt handler. Runs at safe points, may call ereport(FATAL/ERROR) to unwind or LATCH_WAIT_TIMEOUT handling.
  • Safe interruption points — the code base has thousands. Long-running loops need to include CHECK_FOR_INTERRUPTS() — a missing one → uncancelable query.

Common signals + their flags:

  • SIGINT (query cancel) → QueryCancelPending.
  • SIGTERM (shutdown) → ProcDiePending.
  • SIGHUP (reload conf) → ConfigReloadPending.
  • SIGUSR1 (procsignal — multiplexed) → reason-specific flags via procsignal.c.

Auxiliary processes at a glance

Each aux process has its own file with a Main function that the postmaster spawns via SubPostmasterMain (Windows / EXEC_BACKEND) or forks directly:

FileFunctionPurpose
startup.cStartupProcessMainRuns crash recovery / WAL replay at startup. Exits once redo completes.
checkpointer.cCheckpointerMainRuns periodic checkpoints; writes the shutdown stats file.
bgwriter.cBackgroundWriterMainWrites dirty buffers to smooth checkpoint I/O.
walwriter.cWalWriterMainFlushes WAL buffers asynchronously.
walsummarizer.cWalSummarizerMain(PG 17+) Summarizes WAL for incremental backup.
pgarch.cPgArchiverMainArchives completed WAL segments (archive_command / archive_library).
syslogger.cSysLoggerMainRotates + captures postmaster/backend stderr when logging_collector=on.
interrupt.cShared aux-process signal helpersNot a process itself — the signal handlers shared across aux processes.

Bgworker registration

Extensions and core code both use RegisterBackgroundWorker (in postmaster/bgworker.c):

  • Static — called from _PG_init at postmaster start. Fixed slot count (max_worker_processes GUC).
  • DynamicRegisterDynamicBackgroundWorker at runtime; used by parallel query (from a backend) and by extensions.

Bgworkers have flags controlling: shared-memory access, database connection, restart-on-crash policy, restart interval. See knowledge/idioms/background-worker-startup.md for the flag matrix and lifecycle diagram.

Common patch shapes

Add a startup-lifecycle hook

The scenario add-startup-hook (see knowledge/scenarios/add-startup-hook.md) covers this end-to-end. Short version:

  • Hook typically lives in PostmasterMain (postmaster-wide) or InitPostgres (per-backend).
  • Decide: cluster-once vs backend-per-connection.
  • Existing patterns: shared_preload_libraries (postmaster startup), local_preload_libraries + session_preload_libraries (per-backend), ClientAuthentication_hook (auth-time), emit_log_hook (per log record).

Add a new auxiliary process

Rare. Requires:

  • New file under src/backend/postmaster/<name>.c with a <Name>Main function.
  • Registration in postmaster/postmaster.c (grep for StartChildProcess / StartAuxiliaryProcess).
  • Signal handlers (usually delegated to interrupt.c helpers).
  • Shmem region if it exchanges data with backends (via ShmemInit).
  • Consider whether it should restart on crash (postmaster's HandleChildCrash).

Note: for most "run something periodically" use cases, a bgworker is preferable — less core code to touch, extensions can add without a core patch.

Add a signal / interrupt reason

  • New PROCSIGNAL_* constant in src/include/storage/procsignal.h.
  • Signal-dispatcher procsignal_sigusr1_handler case in storage/ipc/procsignal.c.
  • Flag + ProcessInterrupts case in tcop/postgres.c.
  • Setter helper if the reason is per-target-backend (e.g. procsignal_ProcSendSignal(pid, PROCSIG_...))`.
  • Docs for what "kills" or "cancels" this new interrupt cause.

Pitfalls

  • Fork copies memory but not open file descriptors semantically — a palloc before fork is fine (COW), but a dsm_attach before fork is not (the child would double-detach). This is why aux processes and bgworkers do shmem init in their own Main, not inherited state.
  • Signal handlers cannot log via ereport — that's elog(LOG, ...) calls internally allocating in ErrorContext, which is not async-signal-safe. Set a flag, return, let the main loop pick it up via CHECK_FOR_INTERRUPTS.
  • InitPostgres reads pg_authid + pg_database + role/db GUC settings BEFORE the user has issued any SQL — extensions in _PG_init need to be careful about assuming database context is complete.
  • shared_preload_libraries vs session_preload_libraries vs local_preload_libraries — different postmaster/backend load points; different capabilities (shmem allocation is only possible from shared_preload_libraries).
  • Bgworker signal setup — a bgworker inherits SIG_IGN/SIG_DFL from postmaster. It MUST reset signal handlers in its Main via pqsignal calls before doing any interruptible work.
  • proc_exit vs _exit vs abortproc_exit(0) runs registered callbacks (releases locks, detaches shmem, closes files); _exit skips them; abort (PANIC) triggers a cluster-wide restart. Never call _exit in a place that's holding a lock.
  • EXEC_BACKEND builds are Windows-native but also used for testing on Unix — a patch that "works" on your Linux dev box may still fail EXEC_BACKEND CI because the fork-then-exec path is different. Test with -DEXEC_BACKEND locally when touching startup code.

Related corpus

  • Subsystems: tcop (the query loop side), main (backend entry), libpq-backend (auth handshake), access-transam (WAL / xact IDs, needed at startup).
  • Idioms: background-worker-startup, apply-worker-loop, process-utility-hook-chain, abort-transaction-cleanup, crash-recovery-startup.
  • Data structures: pgproc-fields (the per-backend PGPROC slot in shmem).
  • Scenarios: add-startup-hook, add-new-bgworker.
  • File docs: 20 files under knowledge/files/src/backend/postmaster/ + src/backend/tcop/.

Corpus-chain shortcut

python3 scripts/corpus-chain.py --scenario add-startup-hook
python3 scripts/corpus-chain.py --file src/backend/tcop/postgres.c
python3 scripts/corpus-chain.py --file src/backend/postmaster/postmaster.c

Third command in particular surfaces the full 20-file neighborhood of the postmaster tree.

Boundary

Use this skill for backend/aux/bgworker/postmaster lifecycle questions.

Don't use for:

  • libpq / client-side driver — that's src/interfaces/libpq/; different codebase, different lifecycle.
  • Individual SQL commands' handling — that's tcop (dispatch) + commands/ (per-statement).
  • GUC config loading — use gucs-config skill; touches lifecycle but focused on the config side.
  • Extension _PG_init details — use bgworker-and-extensions; this skill covers the invocation timing, not the extension-authoring surface.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,069. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.