Skip to content

Conversation

@ThomasBrady
Copy link
Contributor

@ThomasBrady ThomasBrady commented Oct 31, 2025

Upstreaming as requested by @cosmo0920.

Background:

flb_reload() calls flb_create() to create a new context for validation. flb_create() calls flb_log_create() which calls FLB_TLS_INIT(flb_worker_ctx). On platforms without FLB_HAVE_C_TLS defined (e.g. Windows), FLB_TLS_INIT directly calls pthread_key_create. FLB_TLS_INIT is also called from multiple other locations (flb_lib.c, flb_worker.c, etc.). Each call to pthread_key_create with the same key is undefined behavior per POSIX, causing issues like fluentbit logs not being output after a halted reload.

Summary of changes

This patch makes FLB_TLS_INIT(key) idempotent using pthread_once:
Before: Each FLB_TLS_INIT call directly executed pthread_key_create, causing multiple key creations
After: Each FLB_TLS_INIT uses pthread_once to ensure the key is created exactly once, regardless of how many times or from where it's called

  • Modified FLB_TLS_INIT macro to use pthread_once for one-time initialization
  • Updated FLB_TLS_DEFINE to include pthread_once control and initialization function
  • Added FLB_TLS_DECLARE macro for proper external declarations
  • Fixed headers (flb_log.h, flb_output.h, flb_scheduler.h) to use correct declaration pattern

This ensures thread-safe, idempotent TLS initialization across all compilation units and during hot reload, eliminating the undefined behavior.


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
  • Debug log output from testing the change
  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • Refactor
    • Enhanced internal thread-local storage initialization and synchronization mechanisms.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

Walkthrough

Refactored thread-local storage (TLS) initialization across Fluent Bit by introducing conditional macro patterns and idempotent initialization using pthread_once, ensuring thread-safe single-execution semantics for TLS setup without relying on C11 thread-local storage availability.

Changes

Cohort / File(s) Summary
TLS infrastructure core
include/fluent-bit/flb_thread_storage.h
Replaced simple pthread key initialization with pthread_once pattern; introduced FLB_TLS_DEFINE(type, name) and FLB_TLS_DECLARE(type, name) macros for conditional TLS management; updated conditional logic for TLS key declaration based on FLB_HAVE_C_TLS availability.
Conditional TLS declarations
include/fluent-bit/flb_log.h, include/fluent-bit/flb_output.h, include/fluent-bit/flb_scheduler.h
Applied conditional TLS declaration pattern to public symbols (flb_log_ctx, out_flush_params, sched_timer_coro_cb_params): use FLB_TLS_DECLARE when C TLS unavailable; otherwise use extern FLB_TLS_DEFINE.

Sequence Diagram(s)

sequenceDiagram
    participant Init as Initialization Code
    participant Once as pthread_once
    participant Key as TLS Key
    participant InitFunc as Init Function

    rect rgb(200, 220, 240)
    Note over Init,InitFunc: Old: Direct initialization (unsafe race)
    Init->>Key: Direct pthread_key_create()
    end

    rect rgb(240, 200, 220)
    Note over Init,InitFunc: New: pthread_once pattern (thread-safe)
    Init->>Once: Call FLB_TLS_INIT(key)
    Once->>Once: pthread_once(&once_ctl, init_func)
    Once->>InitFunc: Call init function (once)
    InitFunc->>Key: pthread_key_create()
    Once-->>Init: Return (subsequent calls are no-ops)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Macro design and correctness: Verify FLB_TLS_DEFINE and FLB_TLS_DECLARE macros properly generate per-key pthread_once controls and init functions without naming conflicts or symbol duplication.
  • Conditional compilation paths: Ensure FLB_HAVE_C_TLS conditional logic is correctly applied across all three modified header files (flb_log.h, flb_output.h, flb_scheduler.h) and that linker symbol definitions align with declarations.
  • Thread-safety guarantees: Confirm pthread_once idempotency eliminates prior initialization races and that TLS key lifecycle is correct across multiple compilation units.

Suggested labels

backport to v4.0.x

Suggested reviewers

  • edsiper
  • koleini
  • fujimotos

Poem

🐰 Thread-safe once we declare,
With pthread_once and idempotent care,
No races in the TLS night,
Each thread gets storage, clean and right! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "fix: Make TLS initialization thread-safe and idempotent using pthread_once" directly and accurately describes the primary change in the changeset. The core of this PR is refactoring the FLB_TLS_INIT macro to use pthread_once for idempotent initialization, and updating related header files to support conditional TLS declarations. The title captures this main objective precisely, using specific technical terms (TLS initialization, thread-safe, idempotent, pthread_once) that clearly convey the intent without being verbose or generic.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f879a93 and 289a534.

📒 Files selected for processing (4)
  • include/fluent-bit/flb_log.h (1 hunks)
  • include/fluent-bit/flb_output.h (1 hunks)
  • include/fluent-bit/flb_scheduler.h (1 hunks)
  • include/fluent-bit/flb_thread_storage.h (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
include/fluent-bit/flb_output.h (1)
src/flb_log.c (1)
  • FLB_TLS_DEFINE (50-56)
include/fluent-bit/flb_thread_storage.h (1)
src/flb_log.c (1)
  • FLB_TLS_DEFINE (50-56)
include/fluent-bit/flb_log.h (1)
src/flb_log.c (1)
  • FLB_TLS_DEFINE (50-56)
include/fluent-bit/flb_scheduler.h (1)
src/flb_log.c (1)
  • FLB_TLS_DEFINE (50-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (29)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 32bit, x86, x86-windows-static, 3.31.6)
  • GitHub Check: pr-windows-build / call-build-windows-package (Windows 64bit, x64, x64-windows-static, 3.31.6)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_ARROW=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_ADDRESS=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=On, 3.31.6, gcc, g++)
  • GitHub Check: pr-compile-without-cxx (3.31.6)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-24.04, clang-14)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-centos-7
  • GitHub Check: PR - fuzzing test

Comment on lines +57 to +62
#define FLB_TLS_DEFINE(type, name) \
pthread_key_t name; \
pthread_once_t name##_once = PTHREAD_ONCE_INIT; \
void name##_init_func(void) { \
pthread_key_create(&name, NULL); \
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle pthread_key_create failure to avoid undefined TLS state.

With the new pthread_once wrapper we only invoke pthread_key_create() once. If that call returns an error (e.g. EAGAIN, ENOMEM), the key stays uninitialized but the pthread_once guard prevents any retry, so every later FLB_TLS_SET/GET will operate on an invalid key and the failure is silent. Before this change we at least retried on the next FLB_TLS_INIT, so this is a regression in resiliency. Please capture the return code, surface/log it, and keep the caller from proceeding (e.g. by storing the status in a companion variable that FLB_TLS_INIT checks and aborts or reports). That way we fail fast instead of running with a broken TLS slot.

🤖 Prompt for AI Agents
In include/fluent-bit/flb_thread_storage.h around lines 57 to 62, the
pthread_key_create() result is ignored so if it fails the pthread_once guard
prevents retries and TLS key remains uninitialized; modify the macro to capture
the return code from pthread_key_create into a companion int status variable
(e.g. name##_init_rc), set it atomically, and have
FLB_TLS_INIT/FLB_TLS_GET/FLB_TLS_SET check that status and abort/log/return an
error when non-zero; also log the errno/rc when pthread_key_create fails to
surface the root cause and avoid proceeding with an invalid key.

@edsiper
Copy link
Member

edsiper commented Oct 31, 2025

@codex review

@chatgpt-codex-connector
Copy link

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants