Skip to content

No fork-safety — gunicorn / Celery prefork workers report nothing #3

Description

@AndresL230

Summary

recost/_init.py registers no os.register_at_fork hooks. After a fork:

  • The patched method-object references are inherited (fine — class attrs).
  • The module-level _handle global points at the parent's RecostHandle, but no timer thread is running in the child. Flushes never fire.
  • Transport._local._loop references the parent's asyncio loop, which doesn't exist in the child. run_coroutine_threadsafe raises and is swallowed (_transport.py:195-197). All events queue silently and never send.

Symptom: every gunicorn pre-fork or Celery worker started after init() collects metrics into the void. Most production Python deployments use prefork servers — this is the single largest production gap.

Fix

Register os.register_at_fork(after_in_child=_reinit_after_fork) that re-creates the timer thread and transport thread in the child. Alternatively, document a "call init() in the worker's post_fork hook" pattern and refuse to instrument until init() has been called in the current PID.

Files

  • recost/_init.py
  • recost/_transport.py
  • README.md
  • tests/test_init.py

Priority

P0 — silent total failure on the most common Python production deployment shape.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Blocking / shipping brokenbugSomething isn't workingruntimeRuntime / behavioral bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions