🔢 What is cntr in struct xid_command?
In glibc’s struct xid_command, the field:
volatile int cntr;is used as a synchronization counter to track how many threads still need to process the UID/GID change triggered by __nptl_setxid().
🔄 Role of cntr
-
When a UID/GID change (like
setuid()) is initiated, glibc sends aSIGSETXIDsignal to each thread. -
Each thread runs the
__nptl_setxid_sighandler, which:- Performs the
setuid-like syscall - Decrements
xidcmd->cntr - If the result of decrementing is
1, the current thread is the last one to finish- It then wakes up the initiating thread via futex
- Performs the
🧩 How It’s Used
In the signal handler:
if (atomic_fetch_add_relaxed(&xidcmd->cntr, -1) == 1)
futex_wake((unsigned int *) &xidcmd->cntr, 1, FUTEX_PRIVATE);- Each thread atomically decrements the counter.
- The thread that sees it reach
0(via== 1before subtracting) knows it was the last - It then wakes the initiating thread that is waiting for all threads to complete.
🚦 Why It’s Volatile
- Marked
volatileso that changes are not optimized away or cached across threads. - Ensures correctness in multithreaded, signal-driven context.
📌 Summary
| Field | Purpose |
|---|---|
cntr | Synchronization counter used to detect when all threads have finished applying a UID/GID change |
It’s a simple but effective way to wait for all threads to acknowledge and apply an identity transition in a race-free and safe manner.