fix: mark reference management variables as volatile for thread safety#35211
fix: mark reference management variables as volatile for thread safety#35211
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds the volatile qualifier to several static variables in transComm.c and tref.c, alongside minor formatting and whitespace adjustments. The review feedback correctly points out that using volatile is not a substitute for proper thread synchronization in C, as it does not guarantee atomicity or memory barriers. Since these variables are already managed via synchronization primitives like mutexes or pthread_once, the volatile qualifier is redundant and potentially misleading. Additionally, a duplicate declaration of the mutex array was identified in transComm.c that should be removed for clarity.
| static volatile int32_t refMgt; | ||
| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; |
There was a problem hiding this comment.
The use of volatile for thread safety is a common misconception in C. volatile only prevents the compiler from optimizing memory accesses; it does not provide atomicity or memory barriers required for multi-threaded synchronization. Since these variables are initialized within taosThreadOnce (which typically uses pthread_once), memory visibility is already guaranteed by the synchronization primitive. Using volatile here is unnecessary and misleading regarding the thread-safety guarantees of the code.
static int32_t refMgt;
static int32_t svrRefMgt;
static int32_t instMgt;
static int32_t transSyncMsgMgt;| static volatile int32_t refMgt; | ||
| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; |
There was a problem hiding this comment.
As noted previously, volatile does not provide thread safety or atomicity. These variables are initialized in a thread-safe manner via taosThreadOnce, making the volatile qualifier redundant and potentially hindering compiler optimizations.
static int32_t refMgt;
static int32_t svrRefMgt;
static int32_t instMgt;
static int32_t transSyncMsgMgt;| static volatile int32_t tsRefSetNum = 0; | ||
| static volatile int32_t tsNextId = 0; |
There was a problem hiding this comment.
In C, volatile is not a substitute for proper synchronization primitives. These variables (tsRefSetNum, tsNextId) are already accessed within critical sections protected by tsRefMutex (e.g., in taosOpenRef and taosDecRsetCount). The mutex provides the necessary atomicity and memory visibility guarantees. Adding volatile is redundant and does not add any additional thread safety.
static int32_t tsRefSetNum = 0;
static int32_t tsNextId = 0;| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; | ||
| TdThreadMutex mutex[2]; |
There was a problem hiding this comment.
Pull request overview
Marks several global reference-management counters/IDs as volatile and applies a few minor whitespace / formatting cleanups in util ref handling and transport communication code.
Changes:
- Change multiple global reference-management variables from
int32_ttovolatile int32_t - Minor formatting cleanup (blank lines / line wrapping) in
tref.candtransComm.c
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
source/util/src/tref.c |
Makes tsRefSetNum/tsNextId volatile and cleans up whitespace in ref iteration/locking helpers |
source/libs/transport/src/transComm.c |
Makes ref-manager IDs volatile, wraps a long log line, removes stray whitespace; touches both TD_ASTRA_RPC and non-TD_ASTRA_RPC branches |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static volatile int32_t tsRefSetNum = 0; | ||
| static volatile int32_t tsNextId = 0; |
There was a problem hiding this comment.
Declaring tsRefSetNum/tsNextId as volatile does not make the increments/decrements thread-safe (no atomicity / memory ordering). In this file these variables are already updated under tsRefMutex, so volatile is unnecessary and can give a false sense of correctness. Prefer keeping them non-volatile and relying on the mutex, or convert them to the project’s atomic_* primitives if you need lock-free access.
| static volatile int32_t tsRefSetNum = 0; | |
| static volatile int32_t tsNextId = 0; | |
| static int32_t tsRefSetNum = 0; | |
| static int32_t tsNextId = 0; |
| static volatile int32_t refMgt; | ||
| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; |
There was a problem hiding this comment.
Marking these globals volatile does not provide thread safety or safe publication between threads; it only inhibits certain compiler optimizations. If these IDs are written once in transInitEnv and then treated as immutable, ensure all consumers call transInit (pthread_once provides the needed synchronization) and keep them non-volatile; otherwise use the project’s atomic load/store primitives for cross-thread reads/writes.
| static volatile int32_t refMgt; | |
| static volatile int32_t svrRefMgt; | |
| static volatile int32_t instMgt; | |
| static volatile int32_t transSyncMsgMgt; | |
| static int32_t refMgt; | |
| static int32_t svrRefMgt; | |
| static int32_t instMgt; | |
| static int32_t transSyncMsgMgt; |
| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; | ||
| TdThreadMutex mutex[2]; |
There was a problem hiding this comment.
In the TD_ASTRA_RPC (#else) branch, mutex[2] is defined twice at file scope (once above with multiQ, and again here). This will cause a redefinition compile error when that branch is built. Remove one of the definitions or rename so there is a single shared mutex array.
| TdThreadMutex mutex[2]; |
| static volatile int32_t refMgt; | ||
| static volatile int32_t svrRefMgt; | ||
| static volatile int32_t instMgt; | ||
| static volatile int32_t transSyncMsgMgt; |
There was a problem hiding this comment.
Same as the non-ASTRA branch: volatile does not make these reference manager IDs thread-safe. Use pthread_once + an initialization requirement for callers, or switch to atomic load/store if they can be read/written concurrently.
c8d6f52 to
eae5009
Compare
98ca8ca to
80e617b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| static TdThreadOnce initPoolOnce = PTHREAD_ONCE_INIT; | ||
| int32_t fetchObjRefPool = -1; | ||
| volatile int32_t fetchObjRefPool = -1; |
There was a problem hiding this comment.
Declaring fetchObjRefPool as volatile does not make it thread-safe and is generally not a substitute for atomic operations. This variable is already manipulated via atomic helpers / taosThreadOnce; if you need atomic state transitions, prefer using atomic_* operations (e.g., atomic_exchange_32) and keep the declaration consistent with those APIs rather than using volatile as a synchronization mechanism.
| volatile int32_t clientReqRefPool = -1; | ||
| volatile int32_t clientConnRefPool = -1; |
There was a problem hiding this comment.
volatile does not provide synchronization/atomicity for these ref-pool IDs. They are set during client environment init/cleanup and read across multiple threads; using volatile here can be misleading and doesn’t prevent races. Prefer guarding init/teardown with a mutex or using the project's atomic helpers (e.g., atomic exchange / load) and keep the variables non-volatile unless required by the atomic API signatures.
| typedef struct { | ||
| tmr_h timer; | ||
| int32_t rsetId; | ||
| volatile tmr_h timer; |
There was a problem hiding this comment.
tmr_h is typedef void*, so volatile tmr_h becomes volatile void*. Passing tmqMgmt.timer to APIs like taosTmrStart/taosTmrReset (which take void* handle) will discard the volatile qualifier and, with -Werror enabled in this repo, can break the build. Also, volatile does not provide thread-safety for this handle. Prefer keeping timer as plain tmr_h and use the existing tmqMgmt.lock (or atomics) to coordinate concurrent reads/writes instead.
| volatile tmr_h timer; | |
| tmr_h timer; |
| }; | ||
|
|
||
| extern int32_t fetchObjRefPool; | ||
| extern volatile int32_t fetchObjRefPool; |
There was a problem hiding this comment.
This header change propagates volatile to all users, but volatile does not provide thread-safety and often forces unnecessary volatile loads throughout the codebase. If fetchObjRefPool needs to be accessed concurrently, prefer using the project's atomic helpers at the access sites (and keep the declaration non-volatile unless the atomic API requires a volatile*).
| extern volatile int32_t fetchObjRefPool; | |
| extern int32_t fetchObjRefPool; |
| extern volatile int32_t clientReqRefPool; | ||
| extern volatile int32_t clientConnRefPool; |
There was a problem hiding this comment.
Exposing these globals as volatile in the public client internal header spreads volatile semantics to all translation units, but volatile is not a thread-safety mechanism. Consider keeping these as plain int32_t and enforcing proper synchronization via taosThreadOnce/mutex/atomic helpers at the points where they are written/read concurrently.
| extern volatile int32_t clientReqRefPool; | |
| extern volatile int32_t clientConnRefPool; | |
| extern int32_t clientReqRefPool; | |
| extern int32_t clientConnRefPool; |
80e617b to
85c5ddd
Compare
85c5ddd to
81f2a73
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| volatile int32_t svrRefMgt; | ||
| volatile int32_t instMgt; | ||
| volatile int32_t transSyncMsgMgt; | ||
| TdThreadMutex mutex[2]; |
There was a problem hiding this comment.
In the #else branch (when TD_ASTRA_RPC is defined), mutex[2] is defined twice (once earlier at line ~1301 and again here). If this branch is ever compiled, this will be a redefinition error. Remove one of the definitions or rename/scope them appropriately. While touching this area, also consider restoring static for the refMgt/svrRefMgt/instMgt/transSyncMsgMgt globals if they are not meant to be exported.
| TdThreadMutex mutex[2]; |
81f2a73 to
403457f
Compare
On GCC 7.3, compiler may cache global variable values in registers, making changes from one thread invisible to others.
403457f to
8f772f7
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| volatile void* indexQhandle = NULL; | ||
| volatile int32_t indexRefMgt; |
There was a problem hiding this comment.
Declaring indexQhandle as volatile void* will cause qualifier-discard diagnostics when passing it to APIs taking void* (e.g., taosCleanUpScheduler, taosScheduleTask) under -Werror. Also, volatile doesn’t make publication/use of the handle thread-safe; prefer pthread_once/atomics for safe initialization and keep the handle type unqualified.
| volatile void* indexQhandle = NULL; | |
| volatile int32_t indexRefMgt; | |
| void* indexQhandle = NULL; | |
| int32_t indexRefMgt; |
| // clang-format on | ||
|
|
||
| extern void* indexQhandle; | ||
| extern volatile void* indexQhandle; |
There was a problem hiding this comment.
Exporting indexQhandle as extern volatile void* will force qualifier-discarding conversions at call sites (functions accept void*) and can break builds under -Werror. Keep the declaration as extern void* and use proper synchronization/atomics if you need safe publication.
| extern volatile void* indexQhandle; | |
| extern void* indexQhandle; |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Description
Issue(s)
Checklist
Please check the items in the checklist if applicable.