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.

ITPUB
ITPUB
ITPUB
Why a Barrier‑Based Config Swap Still Crashed: Uncovering a Shallow Copy Bug

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

concurrencyResource ManagementC programmingbug-fixBarrier
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.