677 Commits

Author SHA1 Message Date
mutouyun
3ca2e93b19 feat(ci): add codecov test coverage support to master branch
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.
2025-12-12 07:04:31 +00:00
mutouyun
e38d3ed801 fix(platform): Add FreeBSD detection and include detect_plat.h in detail.h
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.
2025-12-12 07:04:31 +00:00
木头云
542706117a fix(shm_win): Use mem::$delete instead of mem::free in release()
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.
2025-12-12 07:04:31 +00:00
木头云
fc7fa158b6 fix(test): Update test.h include paths after master rebase
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.
2025-12-12 07:04:31 +00:00
木头云
cc33f73eec fix(msvc): Fix C4138 warning by adding space before commented parameter names
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.
2025-12-12 07:04:31 +00:00
木头云
489e75870d fix(test): Fix buffer overflow in data_set caused by array placement new
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.
2025-12-12 07:04:31 +00:00
木头云
8731413d30 refactor(uninitialized): Improve construct() overload resolution
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.
2025-12-12 07:04:31 +00:00
木头云
c39a0cba49 fix(container_allocator): Fix MSVC compilation by correcting allocator semantics
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
2025-12-12 07:04:31 +00:00
mutouyun
90b7badcee Replace custom hash struct with std::hash in unordered_map definition 2025-12-12 07:04:31 +00:00
mutouyun
165060e0b6 Fix the issue caused by inconsistent lifecycle of the global IPC object. 2025-12-12 07:04:31 +00:00
mutouyun
63f35484d7 Refactoring the generic memory allocator 2025-12-12 07:04:31 +00:00
mutouyun
716992cade Reimplement the allocator required for the container type with $new 2025-12-12 07:04:31 +00:00
mutouyun
41529e8eb3 Use $new instead of alloc 2025-12-12 07:04:31 +00:00
mutouyun
189d5f348c Simplify the implementation of memory allocation management 2025-12-12 07:04:31 +00:00
mutouyun
39c7c5c70b The memory allocator supports runtime dynamic size memory allocation 2025-12-12 07:04:31 +00:00
mutouyun
00ee30e339 libipc/memory/resource.h => libipc/mem/resource.h 2025-12-12 07:04:31 +00:00
mutouyun
22c805c7cb Add $new 2025-12-12 07:04:31 +00:00
mutouyun
9a2e1b237a Add block_pool 2025-12-12 07:04:31 +00:00
mutouyun
0035764e0d Adjust the allocator name 2025-12-12 07:04:31 +00:00
mutouyun
93d6c44771 Simplify verify_args function to fix error C3249 2025-12-12 07:04:31 +00:00
mutouyun
9276fcbcda Fix fmt function to handle null pointers and return empty string 2025-12-12 07:04:31 +00:00
木头云
077288e911 Update c-cpp.yml 2025-12-12 07:04:31 +00:00
mutouyun
d00dcbbf15 Fix fmt function to handle empty strings and update make_prefix template parameters 2025-12-12 07:04:31 +00:00
mutouyun
c77a29e9fb Optimize memory_resource & add monotonic_buffer_resource 2025-12-12 07:04:31 +00:00
mutouyun
3693a85aca Add intrusive_stack 2025-12-12 07:04:31 +00:00
mutouyun
397b362338 Add allocator and rewrite allocator_wrapper 2025-12-12 07:04:31 +00:00
mutouyun
7536757064 Optimized partial implementation using fmt 2025-12-12 07:04:31 +00:00
mutouyun
106837ffce Start refactoring memory management, adding memory_resource 2025-12-12 07:04:31 +00:00
mutouyun
975ecba2e3 Update platform-specific feature macros to new interfaces in imp 2025-12-12 07:04:31 +00:00
mutouyun
52951e44f8 Add system 2025-12-12 07:04:31 +00:00
mutouyun
5f75f1d738 Add result 2025-12-12 07:04:31 +00:00
mutouyun
8ec7c6a486 IPC_EXPORT => LIBIPC_EXPORT 2025-12-12 07:04:31 +00:00
mutouyun
ecd1aaac40 Add log 2025-12-12 07:04:31 +00:00
mutouyun
208ac889e7 Add error 2025-12-12 07:04:31 +00:00
mutouyun
d20f88c349 Added fmt support for byte 2025-12-12 07:04:31 +00:00
mutouyun
bc29c85c1a Add fmt 2025-12-12 07:04:31 +00:00
mutouyun
95bf3afe9b Add codecvt 2025-12-12 07:04:31 +00:00
mutouyun
f3ca9a30e8 libimp => libipc 2025-12-12 07:04:31 +00:00
mutouyun
a4eeac7217 Add nameof & scope_exit 2025-12-12 07:04:31 +00:00
mutouyun
1eaadf80f2 Move the export.h file to the imp directory 2025-12-12 07:04:31 +00:00
mutouyun
bf7c6b41e9 Add expected 2025-12-12 07:04:31 +00:00
mutouyun
2e7ab8b34f Add imp for subsequent refactoring 2025-12-12 07:04:31 +00:00
木头云
ab4e5bd18e fix: update library version to 1.4.1 in CMakeLists.txt
Fixes #165

- Update project version in root CMakeLists.txt to 1.4.1
- Update PACKAGE_VERSION in src/CMakeLists.txt to 1.4.1
- Ensures compiled library has correct version number for the upcoming 1.4.1 release
v1.4.1
2025-12-12 06:55:05 +00:00
mutouyun
ce0773b3e6 refactor: improve name handling in shm_posix.cpp to match semaphore pattern
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.
v1.4.0
2025-12-06 16:06:51 +08:00
木头云
addfe4f5cf
Merge pull request #161 from mutouyun/fix/freebsd-mutex-unlock-timing
Fix mutex unlock timing for FreeBSD multi-run stability
2025-12-06 15:22:27 +08:00
木头云
2593213d9c Fix FreeBSD shm_unlink failure by adding '/' prefix in remove()
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.
2025-12-06 07:20:33 +00:00
木头云
37f16cea47 Fix mutex unlock timing to avoid interfering with other references
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.
2025-12-06 06:53:29 +00:00
木头云
0ba12144bd
Merge pull request #160 from mutouyun/issue/156
Fix FreeBSD test failures in POSIX implementation
2025-12-06 14:39:49 +08:00
木头云
5517f48681 Fix FreeBSD segfault by unlocking mutex before destruction
Root cause: FreeBSD's robust mutex implementation (libthr) maintains a per-thread
robust list of mutexes. The error 'rb error 14' (EFAULT - Bad address) indicates
that the robust list contained a dangling pointer to a destroyed mutex.

When a mutex object is destroyed (via close() or clear()), if the mutex is still
in the current thread's robust list, FreeBSD's libthr may try to access it later
and encounter an invalid pointer, causing a segmentation fault.

This happened in MutexTest.TryLockExceptionSafety because:
1. The test called try_lock() which successfully acquired the lock
2. The test ended without calling unlock()
3. The mutex destructor called close()
4. close() called pthread_mutex_destroy() on a mutex that was:
   - Still locked by the current thread, OR
   - Still in the thread's robust list

Solution:
Call pthread_mutex_unlock() before pthread_mutex_destroy() in both close()
and clear() methods. This ensures:
1. The mutex is unlocked if we hold the lock
2. The mutex is removed from the thread's robust list
3. Subsequent pthread_mutex_destroy() is safe

We ignore errors from pthread_mutex_unlock() because:
- If we don't hold the lock, EPERM is expected and harmless
- If the mutex is already unlocked, this is a no-op
- Even if there's an error, we still want to proceed with cleanup

This fix is platform-agnostic and should not affect Linux/QNX behavior,
as both also use pthread robust mutexes with similar semantics.

Fixes the segfault in MutexTest.TryLockExceptionSafety on FreeBSD 15.
2025-12-06 06:35:02 +00:00
木头云
47fa303455 Fix segfault in EOWNERDEAD handling - remove incorrect ref count manipulation
Root cause: The previous code incorrectly called shm_->sub_ref() when handling
EOWNERDEAD, which could cause the shared memory to be freed prematurely while
the mutex pointer was still in use, leading to segmentation fault.

Fix: Remove the shm_->sub_ref() call. When EOWNERDEAD is returned, it means
we have successfully acquired the lock. We only need to call pthread_mutex_consistent()
to make the mutex usable again, then return success. The shared memory reference
count should not be modified in this path.

This fixes the segfault in MutexTest.TryLockExceptionSafety on FreeBSD 15.
2025-12-06 06:21:38 +00:00