fix alignment different between c and c++ in gtest#3331
Conversation
Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## unstable #3331 +/- ##
============================================
- Coverage 74.98% 74.97% -0.02%
============================================
Files 129 129
Lines 71551 71632 +81
============================================
+ Hits 53654 53705 +51
- Misses 17897 17927 +30
🚀 New features to boost your workflow:
|
|
TBH, I don't like very much to replace Is it possible Or use aliases like Edit: Found this discussion about stdatomic.h with C++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60932. The comment at the bottom:
So, let's bump to C++20? Unit tests are only for developers, not for users who just want to build Valkey. For that, you only need C11. |
|
Another option is that we use the style If we do that, then we'll be able to define for the C++ tests: #define _Atomic(type) alignas(sizeof(type)) typeIf some C code uses |
Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
|
@zuiderkwast Thanks for the suggestions! I agree that VALKEY_ATOMIC adds unnecessary indirection. I've adopted your second approach:
|
zuiderkwast
left a comment
There was a problem hiding this comment.
Yeah, this looks better to me. :)
|
@cjx-zar Going back to the original issue... are you saying that on a 32-bit system, a Can you provide a bit more information about the before/after situation? EDIT: I may have answered by own question. It seems that |
JimB123
left a comment
There was a problem hiding this comment.
Nice find. I would have never guessed that _Atomic alters the alignment.
|
Oops, I was just editing the top comment before merging it. The top comment is used as the commit message when we're squash-merging, so it's good to make sure it matches what's actually being committed. Now the commit message mentions the wrong macro name, which was used in this PR before the review comments and updates. |
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration `int aof_rewrite_for_replication;` between https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L1843 and https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/server.h#L2108 The crash is caused by https://github.com/valkey-io/valkey/blob/fc217fca2d7de246ab8494d9d8619b7348235f47/src/unit/wrappers.h#L40 stripping the _Atomic qualifier in C++ builds. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault. I added VALKEY_ATOMIC, and it works as follows: - C builds (production): VALKEY_ATOMIC(uint64_t) -> _Atomic uint64_t (unchanged behavior) - C++ builds (tests via wrappers.h): VALKEY_ATOMIC(uint64_t) -> alignas(8) uint64_t (preserves 8-byte alignment) - All existing atomic_load_explicit / atomic_store_explicit calls in C code continue to work because _Atomic is present in C mode - C++ test code only does direct field access (never uses atomic operations), so alignas(N) type is sufficient --------- Signed-off-by: cjx-zar <jxchenczar@foxmail.com>
I found that on 32-bit platforms, the gtest fails if I add a declaration
int aof_rewrite_for_replication;between two atomic 64-bit fields in the valkeyServer struct.In C, the _Atomic modifier makes the type aligned to its own size, but for the C++ unit tests, we're stripping the _Atomic qualifier in src/unit/wrappers.h by defining it to empty. This makes struct valkeyServer have different alignment/field offsets in C-compiled code (libvalkey.a) vs C++-compiled tests (gtest). As a result, fields after these atomics are accessed at different offsets, leading to corrupted reads/writes and a segfault.
This commit changes
_Atomicto always use parentheses, as in_Atomic(int)instead of_Atomic int, and for C++ defines it to be aligned in the same way as in C: