Intermittent CI failure of test_dd_conformance.py::test_init_populates_identity_and_dd_env in py-mando, root-caused to leaked background Axum server threads (spawned merely by constructing AlgoRunner) racing a non-thread-safe logger.init(). A threading.Lock mitigation shipped on develop (MR !601), but it is not a proven 100% fix.
For Agents
This is a shared-mutable-state cross-test race, same bug CLASS as the env-var flakes in mando-known-flaky-tests-2026-07-15. The shipped
Locknarrows the window by orders of magnitude but a residual microsecond window remains. Do NOT treat the flake as fully closed; the real fix (stop leaking server threads / stop asserting on module globals) needs its own ticket.
Symptom
assert lg.identity["service"] == "bess-os-algo-optimization"
# fails: identity["service"] is None
- Intermittent, timing-dependent. Passes on retry.
- Seen on
develop@ab4c54c1(pipeline2746786029); can hit any branch carrying the DD-conformance suite. - Tell: the log lines
Starting Algo runner service, listening on 127.0.0.1:3003and.../3002appear interleaved right before the failing test. Those are the leakedAlgoRunnerserver threads emitting.
Root cause
A chain of three defects across the Rust/Python boundary:
- Construction spawns a permanent thread.
py-mando/src/algo_runner.rsAlgoRunner::new(around line 113) doesstd::thread::spawn(... start_server ...). Just constructing anAlgoRunnerlaunches a background Axum server thread. Its graceful shutdown only fires on Ctrl+C / SIGTERM, so inside pytest it never stops. start_serverre-inits the logger with no service arg.start_servercallsinit_logger(py), which calls Pythonpy_mando.logger.init()with no service argument (service defaults toNone).logger.init()is not thread-safe.py-mando/python/py_mando/logger.pyinit()sets the globalidentityon one line, but only sets_initialized = Trueseveral slow lines later — the gap includesimport ddtrace.auto. That is a wide race window.
test_algo_runner.py constructs AlgoRunner twice (test_algo_runner_creation on port 3002, test_algo_runner_run_method on port 3003) and leaks both server threads. Their init() calls fire asynchronously during the LATER test_dd_conformance run. A background init() (service=None) landing inside the window overwrites identity with {"service": None, ...}, so the assertion sees None.
Two module globals (identity, _initialized) mutated by leaked background threads, plus a test that resets _initialized = False, equals a shared-state collision.
Mitigation shipped (not a guaranteed fix)
- What: a double-checked
threading.Lockaround the body oflogger.init(). - Where: merged to
developvia MR !601, branchfeature/BE-4067, commitfix: guard py-mando logger init against concurrent initialization. - Effect: closes the WIDE window (the slow
ddtraceimport) and cuts flake probability by orders of magnitude.
Not a proven 100% fix
A residual microsecond window remains: a background
init()in-flight at the instanttest_dd_conformanceresets_initializedstill loses. Treat the flake as heavily reduced, not eliminated.
Real 100% fix (needs its own ticket)
Remove the shared-state collision at the source. Either:
AlgoRunnershould not spawn an unstoppable server thread just to be constructed, ortest_dd_conformanceshould not assert on module globals that live background threads mutate — isolate via a localmonkeypatchofidentity/_initialized, or run the test in a fresh process.
Merge / rebase gotcha observed
MR !601’s diff previewed conflicts in opl.rs and ts_data_retrieve.rs (via git merge-tree), but git rebase origin/develop resolved them automatically by dropping 5 branch commits as “patch contents already upstream”. Those error-unwalling commits had already reached develop through another MR. merge-tree previews such conflicts as real; rebase recognises the duplicate patches and drops them. Lesson: a merge-tree conflict preview is not proof of a real rebase conflict when the branch’s commits may already be upstream.
Related
- mando-known-flaky-tests-2026-07-15 — same shared-mutable-state race class; cross-linked there
- py-mando
- BE-4067 whole-mando error unwalling
- BE-4067 error DX clarity
- BE-3613 Algo Services py-mando Conformance
- BE-3482 Datadog Logs and APM Conformance