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
    • Improved thread-local storage initialization to be safer and idempotent across threads.
    • Standardized conditional declarations for per-thread storage so thread-specific data is reliably allocated and linked based on platform capabilities.
    • Reduced risk of race conditions during TLS setup and clarified initialization semantics without changing external behavior.

@coderabbitai
Copy link

coderabbitai bot commented Oct 31, 2025

Walkthrough

Introduces idempotent pthread_once-based TLS initialization macros and conditional TLS declarations; updates several public TLS-backed symbols to use FLB_TLS_DECLARE when C TLS is unavailable or extern FLB_TLS_DEFINE otherwise.

Changes

Cohort / File(s) Summary
TLS infrastructure core
include/fluent-bit/flb_thread_storage.h
Reworked TLS init to use pthread_once-guarded per-key init functions; added FLB_TLS_DEFINE(type, name) and FLB_TLS_DECLARE(type, name) macros; changed FLB_TLS_INIT to idempotent pthread_once pattern; conditional extern/declare handling for flb_worker_ctx.
Conditional TLS declarations
include/fluent-bit/flb_log.h, include/fluent-bit/flb_output.h, include/fluent-bit/flb_scheduler.h
Replaced single extern FLB_TLS_DEFINE(...) declarations with conditional blocks: FLB_TLS_DECLARE(...) when FLB_HAVE_C_TLS is not defined, otherwise extern FLB_TLS_DEFINE(...), for flb_log_ctx, out_flush_params, and sched_timer_coro_cb_params.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as TLS user (any CU)
    participant FLB_API as FLB_TLS_INIT / macro
    participant Once as pthread_once
    participant InitFn as per-key init function
    participant Key as pthread_key_t

    rect rgb(240, 248, 255)
    Note over Caller,FLB_API: New flow — idempotent per-key init
    Caller->>FLB_API: Access TLS (macro ensures init)
    FLB_API->>Once: pthread_once(&once_ctl, InitFn)
    Once->>InitFn: call (first time only)
    InitFn->>Key: pthread_key_create(&key, destructor)
    InitFn-->>Once: return
    Once-->>FLB_API: return (subsequent no-op)
    FLB_API-->>Caller: provide thread-local storage
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • include/fluent-bit/flb_thread_storage.h — macro correctness, naming collisions, and symbol visibility.
    • Conditional compilation around FLB_HAVE_C_TLS across headers to ensure consistent declarations/definitions and linker behavior.
    • Ensure per-key pthread_once functions are unique per TLS key and that destructors/lifetimes are correct.

Suggested labels

backport to v4.0.x

Suggested reviewers

  • edsiper
  • koleini
  • fujimotos

Poem

🐰 I hopped through headers, crisp and sly,
Once called once, no race in my eye,
Threads each get their cozy nook,
TLS settled—no more rook,
A carrot-coded cheer — hop, high! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: making TLS initialization thread-safe and idempotent using pthread_once, which aligns with the core modifications across the TLS-related header files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

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

📒 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)
🚧 Files skipped from review as they are similar to previous changes (2)
  • include/fluent-bit/flb_output.h
  • include/fluent-bit/flb_scheduler.h
🧰 Additional context used
🧬 Code graph analysis (2)
include/fluent-bit/flb_log.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)
⏰ 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). (30)
  • 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: pr-windows-build / call-build-windows-package (Windows 64bit (Arm64), amd64_arm64, -DCMAKE_SYSTEM_NAME=Windows -DCMA...
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=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_SIMD=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_THREAD=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_COVERAGE=On, 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_SIMD=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SIMD=Off, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SANITIZE_MEMORY=On, 3.31.6, gcc, g++)
  • 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, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_JEMALLOC=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 (-DSANITIZE_ADDRESS=On, 3.31.6, gcc, g++)
  • GitHub Check: run-ubuntu-unit-tests (-DSANITIZE_UNDEFINED=On, 3.31.6, gcc, g++)
  • 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=Off, 3.31.6, clang, clang++)
  • GitHub Check: run-ubuntu-unit-tests (-DFLB_SMALL=On, 3.31.6, clang, clang++)
  • GitHub Check: PR - fuzzing test
  • 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, clang, clang++, ubuntu-22.04, clang-12)
  • GitHub Check: pr-compile-system-libs (-DFLB_PREFER_SYSTEM_LIBS=On, 3.31.6, gcc, g++, ubuntu-22.04, clang-12)
  • 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-centos-7

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".

@edsiper
Copy link
Member

edsiper commented Nov 4, 2025

@ThomasBrady pls adjust the commit message , it must be prefixed with the file interface name (https://github.com/fluent/fluent-bit/blob/master/CONTRIBUTING.md#commit-changes)

image

@edsiper edsiper added this to the Fluent Bit v4.2 milestone Nov 4, 2025
…hread_key_create once for each key

This patch ensures pthread_key_create is only called once per TLS key
by using pthread_once for thread-safe idempotent initialization. This
prevents race conditions and errors when FLB_TLS_INIT is called from
multiple locations (different compilation units, hot reloads, etc).

Changes:
- Modified FLB_TLS_INIT macro to use pthread_once control structure
- Updated FLB_TLS_DEFINE to include pthread_once_t and init function
- Added FLB_TLS_DECLARE macro for external TLS key declarations
- Updated flb_log.h, flb_output.h, and flb_scheduler.h to use new
  FLB_TLS_DECLARE for proper extern declarations

The implementation wraps pthread_key_create in a function called via
pthread_once, guaranteeing single initialization regardless of how
many times FLB_TLS_INIT is invoked.

Signed-off-by: Thomas Brady <thomas.brady@chronosphere.io>
@ThomasBrady
Copy link
Contributor Author

@ThomasBrady pls adjust the commit message , it must be prefixed with the file interface name (https://github.com/fluent/fluent-bit/blob/master/CONTRIBUTING.md#commit-changes)

image

Done 👍

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