# C++ metrics callback shutdown and worker cleanup

A metrics capture callback calling `Stop()` could abort its embedding process.
The corrected endpoint requests shutdown from its own worker, refuses restart
until an external caller joins that worker, and cleans up independently of the
running flag. The FIXP wrapper inherits the same correction. No session-path
lock, allocation or socket operation is added.

## Reproductions

At `551e2de07`, four real-socket regressions terminate with exit 134 and
`std::system_error: Resource deadlock avoided`: classic FIX and FIXP over both
TCP and Unix-domain sockets. The public capture callback calls the endpoint's
public `Stop()`; no scheduling shim or production hook is involved. The
original endpoint unconditionally joins its own thread after clearing its
running flag. Catching that self-join exception alone would still leave the
joinable worker and its resources behind because a later `Stop()` returned
early on the already-cleared flag.

A separate one-shot `poll` interposer returns EINVAL at the worker's real
socket wait. All four original-header probes fail because `Running()` stays
true after the worker exits. The fixed probes require stopped status, reject
replacement of the still-joinable thread, externally join and clean up, and
then successfully restart and serve a request. Each log contains exactly one
fault marker. The archived original header is compiled through its include
guard with the new probe; the retained baseline binary uses the unmodified
endpoint implementation, not a mocked loop.

## Lifetime contract

Start, external Stop and destruction remain serialized lifecycle operations;
the change does not promise arbitrary concurrent control callers. Capture or
render callbacks may request Stop, including while another thread is already
joining that worker. A thread-local worker marker avoids reading the
`std::thread` object from its own callback while an external join mutates it,
or before Start finishes assigning a newly created worker.

The callback's endpoint and sources must remain alive until an external Stop
returns. Callback Stop does not free the active render buffer, close its
listener, join itself or permit a new lifetime. The worker publishes stopped
status when its loop exits; an external Stop still joins and releases resources
even when that flag is already false. Destroying the endpoint from its own
callback is not supported.

## Verification

The corrected source patch over `551e2de07` passes five complete binaries in
each of three configurations: GCC 14 development, GCC 14 open, and Clang 21
open with AddressSanitizer, UndefinedBehaviorSanitizer and leak detection.
The binaries are `test_fix_metrics_callback_stop`, `test_fix_metrics_http`,
`test_fix_metrics_http_portable`, `test_fixp_metrics_http` and
`test_fix_operations_profile`. All 15 runs pass with no explicit skip markers.
The portable owner is exercised on Linux; these runs are not Windows or BSD
runtime qualification.

The new callback suite checks eight combinations: both schemas and both
transports, with either later external cleanup or an external Stop blocked
while the callback remains active. It checks two callback Stop requests,
callback and external restart refusal, no successful scrape after shutdown,
Unix-path cleanup, idempotent external Stop and successful reuse. Eight
separate fault probes pass across both ordinary editions. All recorded source
and driver hashes remain unchanged during the fixed run. Export scanning
reports zero findings; whitespace checks pass.

`~/archive/libhft/cpp-metrics-callback-20261011/` retains `baseline/`,
`worker-baseline/` and `fixed/`, including source pins, patches, toolchain and
build output, per-case logs and source manifests. The initial test compilation
failed on a misspelled process-ID helper; that log is retained separately from
the corrected baseline build. Drivers and the poll shim are tracked under
`internal/docs/bench/evidence/cpp-metrics-callback-20261011/`.

These are functional lifetime and coarse shutdown checks under a shared CPU
lease on hp, with external build outputs. They establish neither NIC latency
nor completion of the all-flavours review.
