- Add codecov.yml configuration to exclude 3rdparty, test, and demo directories
- Update GitHub Actions workflow with exclude parameter in codecov-action
- Ensures only project source code is included in coverage metrics
This provides double protection:
1. codecov.yml filters on CodeCov service side
2. workflow exclude filters during upload
Add CodeCov test coverage configuration:
- Add LIBIPC_CODECOV option to CMakeLists.txt with coverage compilation flags
- Add CodeCov badge to README.md for coverage status display
Note: The codecov.yml workflow file needs to be added manually
or requires workflows permission to push.
Fixed two critical issues from the rebase:
1. Added LIBIPC_OS_FREEBSD macro definition in detect_plat.h to enable
FreeBSD platform detection alongside other OS checks
2. Added missing #include "libipc/imp/detect_plat.h" in detail.h to
properly include platform detection macros
These fixes ensure FreeBSD compilation will work correctly with the
unified platform detection system.
The acquire() function allocates id_info_t using mem::$new<id_info_t>(),
so the release() function must use mem::$delete(ii) to deallocate it,
not mem::free(ii). This ensures proper allocation/deallocation pairing.
Issue: Memory allocated with mem::$new must be freed with mem::$delete
to maintain consistent memory management semantics.
After rebasing onto master, test.h was moved to test/archive/.
Updated include paths in test subdirectories:
- test/imp/*.cpp: "test.h" -> "../archive/test.h"
- test/mem/*.cpp: "test.h" -> "../archive/test.h"
- test/concur/*.cpp: "test.h" -> "../archive/test.h"
This ensures all test files can properly find the test header
after the directory reorganization in master branch.
ISSUE:
MSVC compiler reports warning C4138: '*/' found outside of comment
for patterns like 'void */*p*/' where the pointer asterisk is immediately
followed by a comment start.
AFFECTED FILES:
- include/libipc/mem/new.h (line 30)
- src/libipc/platform/win/mutex.h (line 54)
- src/libipc/platform/win/semaphore.h (line 53)
CHANGES:
Changed 'type */*param*/' to 'type * /*param*/' (added space before comment)
Examples:
- void */*p*/ → void * /*p*/
- char const */*name*/ → char const * /*name*/
This resolves the MSVC warning while maintaining code functionality
and keeping the commented-out parameter names for documentation.
ROOT CAUSE:
Array placement new (::new(buffer) T[N]) adds a hidden cookie (array size)
before the array elements in some compiler implementations (particularly MSVC).
The cookie is used for proper array destruction. However, the data_set buffer
was sized only for sizeof(T[N]), not accounting for the cookie overhead.
ISSUE:
- Buffer allocated: sizeof(rand_buf[LoopCount])
- Actual space needed: sizeof(cookie) + sizeof(rand_buf[LoopCount])
- Result: Cookie and part of array written beyond buffer boundary
- Consequence: Memory corruption, leading to invalid pointers in buffer objects
SYMPTOM:
In IPC.1v1 test, memcpy(buf, data, size) crashed because 'data' pointer
(from buffer::data()) pointed to corrupted/invalid memory address.
SOLUTION:
Replace array placement new with individual element placement new:
- Cast buffer to array pointer directly (no cookie needed)
- Construct each element individually with placement new
- Manually destroy each element in destructor
This approach:
- Eliminates cookie overhead
- Provides precise control over object lifetime
- Works consistently across all compilers
Fixes crash in IPC.1v1 test case on MSVC.
IMPROVEMENTS:
1. Add explicit zero-argument overload to avoid SFINAE ambiguity
2. Require at least one argument (A1) for parameterized overloads
3. Better separation between direct initialization and aggregate initialization
BENEFITS:
- Clearer intent: zero-argument construction is explicitly handled
- Avoids potential SFINAE ambiguity when empty parameter pack is used
- More maintainable: easier to understand which overload is selected
- Consistent with modern C++ best practices for variadic templates
TECHNICAL DETAILS:
- Zero-arg overload: Always uses T() for value initialization
- One-or-more-arg overload: Uses SFINAE to choose between:
* T(args...) for types with matching constructor
* T{args...} for aggregate types or types with initializer_list ctor
This is a code quality improvement and does not fix any compilation issues,
but provides better template overload resolution.
ROOT CAUSE:
The allocate() function was incorrectly constructing objects during memory
allocation, violating C++ allocator requirements. MSVC's std::_Tree_node has
a deleted default constructor, causing compilation failure.
CHANGES:
- container_allocator::allocate() now only allocates raw memory without
constructing objects (removed mem::$new and ipc::construct calls)
- container_allocator::deallocate() now only frees memory without
destroying objects (removed mem::$delete and ipc::destroy_n calls)
WHY THIS FIXES THE ISSUE:
C++ allocator semantics require strict separation:
* allocate() -> raw memory allocation only
* construct() -> object construction with proper arguments
* destroy() -> object destruction
* deallocate() -> memory deallocation only
Standard containers (like std::map) call construct() with proper arguments
(key, value) to initialize nodes, not allocate(). Since std::_Tree_node in
MSVC has no default constructor (= delete), attempting to construct it
without arguments always fails.
Fixes MSVC 2017 compilation error:
error C2280: 'std::_Tree_node<...>::_Tree_node(void)':
attempting to reference a deleted function
Check if name already starts with '/' before adding prefix, consistent
with the pattern used in semaphore_impl.h. This avoids duplicate prefix
when users provide names in the correct format.
Problem: Tests fail on the second run on FreeBSD with ShmTest.RemoveByName failing.
After the first test run completes, subsequent runs fail because shared memory
objects are not properly removed.
Root cause: FreeBSD's shm_unlink() is stricter than Linux about POSIX compliance.
The remove(char const * name) function was calling shm_unlink() without the '/'
prefix, while acquire() was using '/'+name format. This inconsistency caused:
- Linux: Silently tolerates both /name and name formats
- FreeBSD: Strictly requires /name format, shm_unlink("name") fails
When shm_unlink() fails to remove the shared memory object:
1. First test run creates /remove_by_name_test_1
2. Test calls shm::remove("remove_by_name_test_1")
3. shm_unlink("remove_by_name_test_1") fails on FreeBSD (missing '/')
4. Shared memory object remains in the system
5. Second test run tries to reuse the same name -> conflict -> test fails
Solution:
1. Fix remove(char const * name) to prepend '/' to the name for consistency
with acquire() function, ensuring POSIX compliance
2. Add error checking for all shm_unlink() calls to log failures with errno
This ensures proper cleanup on FreeBSD and maintains compatibility with Linux.
Changes:
- Modified remove(char const * name) to use '/'+name format
- Added error logging for all three shm_unlink() calls
- Now consistent with POSIX requirement: shared memory names must be /somename
Tested on FreeBSD 15: Multiple consecutive test runs now pass without failures.
Problem: The previous fix unconditionally called pthread_mutex_unlock() at the
beginning of close(), which could interfere with other threads/processes that
still had valid references to the mutex. This caused test failures on FreeBSD
when running tests multiple times (ShmTest.RemoveByName would fail on the second run).
Root cause: Calling unlock() too early could affect the mutex state for other
references that are still using it, leading to unexpected behavior.
Solution: Move pthread_mutex_unlock() to only be called when we're about to
destroy the mutex (i.e., when we're the last reference: shm_->ref() <= 1 &&
self_ref <= 1). This ensures:
1. We don't interfere with other threads/processes using the mutex
2. We still unlock before destroying to avoid FreeBSD robust list issues
3. The unlock happens at the correct time - right before pthread_mutex_destroy()
This is the correct approach because:
- Only the last reference holder should clean up the mutex
- Unlocking should be paired with destroying for the final cleanup
- Other references should not be affected by one reference closing
Fixes the second-run test failure on FreeBSD while maintaining the segfault fix.