Why a Barrier‑Based Config Swap Still Crashed: Uncovering a Shallow Copy Bug
A seemingly safe configuration swap using barriers caused a crash because a shallow copy duplicated resource pointers, leading to premature freeing of the active configuration; the article explains the bug, shows the faulty code, and presents a corrected approach.
Problem Overview
The author encountered a bug in a multithreaded configuration update routine that, despite using barriers to avoid locks, still caused crashes due to an incorrect logic flow.
Original Implementation
void reset_res(res_config, new_res) {
old_res = res_config->res;
res_config->res = new_res;
barrier();
free_res(old_res);
}
int modify_config() {
new_res_config = duplicate(old_res_config);
new_res = new_res();
reset_res(new_res_config, new_res);
config->res_config = new_res_config;
barrier();
free_res_config(old_res_config);
}Barrier Guarantees
In both reset_res and modify_config, the barrier() call ensures that all worker threads have completed the current loop, so no thread can still reference the old resource when it is freed.
Bug Cause
modify_config aims to change the configuration without blocking worker threads.
It replaces pointers and uses a barrier to complete the update. new_res_config = duplicate(old_res_config) copies the old configuration.
The new resource new_res is created and reset_res swaps and frees the old resource.
Finally, config->res_config = new_res_config and another barrier finalize the update.
The bug appears in step 3: duplicate performs a shallow copy (essentially a memcpy), so new_res_config and config->res_config end up pointing to the same memory. After reset_res frees that memory, the configuration still points to a freed resource, causing a crash.
Proposed Fix
config->res_config = new_res_config;
barrier();
reset_res(new_res_config, new_res);Moving the assignment before reset_res prevents the freed‑resource pointer from being used later, but the logic feels unnatural because the configuration is updated before the new resource is fully prepared.
Recommended Normal Logic
A cleaner approach is:
Duplicate the configuration without copying resource pointers (shallow copy only the config structure).
Call reset_res(new_res_config, new_res) to obtain and assign the new resource.
Assign the updated configuration: config->res_config = new_res_config; Finally, invoke barrier() to synchronize threads.
Conclusion
The crash was caused by an improper shallow copy in the duplicate function, which duplicated resource pointers and led to premature freeing. Adjusting the order of operations and ensuring deep copies of resources eliminates the bug and results in a safer, lock‑free configuration update.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
