- Remove src/libipc/utility/log.h as it's no longer used
- All code has been migrated to use the new libipc/imp/log.h interface
- The old utility/log.h provided printf-style logging: ipc::log() and ipc::error()
- The new imp/log.h provides modern C++ stream-based logging with LIBIPC_LOG() macro
- Verified that there are no remaining references to utility/log.h in the codebase
This completes the log interface migration by removing the deprecated file.
- src/libipc/platform/win/get_sa.h:
* Move 'struct initiator' definition outside get_sa() function
* Rename to 'sa_initiator' to avoid naming conflicts
* Define at namespace ipc::detail scope (above get_sa function)
* Keep template constructor: template <typename Logger> sa_initiator(Logger const &log)
* get_sa() now simply uses: static sa_initiator handle(log);
This fixes the C++ standard violation:
- C++03/11/14/17/20 all prohibit local classes from having member templates
- Error C2892: 'local class shall not have member templates'
- Moving the struct to namespace scope resolves this issue
The struct is now a proper namespace-level definition with a template
constructor, which is fully compliant with C++ standards.
- src/libipc/platform/win/get_sa.h:
* Change from class template to constructor template
* Keep 'struct initiator' as a regular class (not template)
* Make constructor a function template: template <typename Logger> initiator(Logger const &log)
* Instantiate as: static initiator handle(log);
* This is valid C++ as function templates can be defined inside functions
* Fixes the issue that class templates cannot be defined inside functions
The constructor template approach allows proper logger passing while
maintaining valid C++ syntax for local struct definitions.
- src/libipc/platform/win/get_sa.h:
* Convert initiator struct to template with Logger parameter
* Pass log object from get_sa() to initiator constructor via template
* Use 'static initiator<decltype(log)> handle(log)' to instantiate
* This allows initiator constructor to properly access log object
* Syntax: initiator(Logger const &log) receives the logger
- src/libipc/platform/win/semaphore.h:
* Fix format error on line 79: remove extra characters '"}]'
* Correct closing of log.error() statement
* Before: log.error(...)"}]
* After: log.error(...);
These fixes resolve the static struct initialization issue and
code format error in Windows platform.
- src/libipc/platform/win/get_sa.h:
* Fix malformed log.error() calls on lines 19 and 23
* Remove extra comma and parenthesis: GetLastError(, -> GetLastError()
* Fix closing parenthesis and bracket placement
* Line 19: GetLastError(, "]"))) -> GetLastError()), "]"
* Line 23: GetLastError(, "]"))) -> GetLastError()), "]"
- src/libipc/platform/win/mutex.h:
* Add missing LIBIPC_LOG() to try_lock() function at line 84
* The function uses log.error() at line 95 and needs logger initialization
These fixes resolve Windows compilation errors related to malformed
log calls and missing LIBIPC_LOG() macro.
- src/libipc/ipc.cpp:
* Add LIBIPC_LOG() to chunk_storages::get_info() member function
* This was missing, causing 'log' to be undeclared at line 245
* The get_info() function uses log.error() for chunk storage errors
This completes the fix for all missing LIBIPC_LOG() initializations
in the ipc.cpp file.
- src/libipc/prod_cons.h:
* Add LIBIPC_LOG() to second force_push() template function
* This was missing, causing 'log' to be undeclared at line 379
- src/libipc/ipc.cpp:
* Add LIBIPC_LOG() to static send() function (line 590)
* Capture log by reference in outer lambda: [tm, &log]
* Capture log by reference in inner lambda: [tm, &log, info, que, msg_id]
* This fixes 'log' was not declared error in lambda at line 598
* The log variable is now properly captured from the outer send() scope
These fixes ensure that all functions using log.debug/error/warning
have proper LIBIPC_LOG() initialization and lambda captures.
- src/libipc/platform/posix/condition.h:
* Replace all %d and %s format specifiers with stream-based syntax
* Update log.error() calls to use proper streaming (e.g., "[", eno, "]")
- src/libipc/platform/posix/semaphore_impl.h:
* Remove %d format specifiers from log.error() calls
* Fix malformed parentheses (e.g., .c_str(, ""))
* Remove unnecessary empty string arguments
* Use stream-based logging consistently
- src/libipc/platform/win/mutex.h:
* Fix malformed GetLastError() parentheses
* Remove %lu format specifier, use explicit cast instead
* Update to stream-based logging syntax
- src/libipc/platform/win/semaphore.h:
* Fix malformed GetLastError() parentheses
* Remove %lu format specifier, use explicit cast instead
* Update to stream-based logging syntax
All format specifiers (%d, %s, %zd, %p, %lu) have been removed and replaced
with proper C++ stream-based logging that is type-safe and consistent with
the new imp/log interface.
- Add LIBIPC_LOG() to functions in platform files that use log.error/warning/debug
- Fixed files:
- POSIX platform: mutex.h, semaphore_impl.h, shm_posix.cpp
- Windows platform: get_sa.h, mutex.h, semaphore.h, shm_win.cpp
- Sync layer: condition.cpp, mutex.cpp, semaphore.cpp
All functions using the new log interface now properly initialize the logger with LIBIPC_LOG()
- Add LIBIPC_LOG() to calc_wait_time() function
- Add LIBIPC_LOG() to make_timespec() function
- Both functions use log.error() and need the logger initialization
- Fix multi-parameter log calls with complex formatting in POSIX and Windows platforms
- Replace remaining ipc::error() and ipc::log() calls with log.error() and log.warning()
- Handle special cases:
- POSIX condition.h: pthread_cond_timedwait multi-param formatting
- POSIX get_wait_time.h: calc_wait_time multi-param formatting
- POSIX semaphore_impl.h: sem_timedwait multi-param formatting
- Windows mutex.h: WaitForSingleObject with hex formatting, WAIT_ABANDONED as warning
- Windows semaphore.h: WaitForSingleObject and ReleaseSemaphore calls
- Use std::hex/std::dec for hexadecimal formatting in Windows platform
- All log interface migrations now complete
- Replace include "libipc/utility/log.h" with "libipc/imp/log.h"
- Add LIBIPC_LOG() at the beginning of functions that use logging
- Replace all ipc::error() calls with log.error()
- Replace all ipc::log() calls with log.debug() or log.error() based on context
- Modified functions:
- cc_acc(): error logging for shm acquire failure
- make_handle(): error logging for chunk storage operations
- find_storage(): error logging for invalid storage id
- release_storage(): error logging for invalid storage id
- recycle_storage(): error logging for invalid storage id
- clear_message(): error logging for invalid message size
- send(): error logging for various send failures, debug logging for force_push
- recv(): error logging for various recv failures
- Use type-safe streaming interface instead of printf-style formatting
- Remove manual newline characters from log messages
- Total changes: 19 log call sites updated
- Update force_push() log calls to use log.debug() instead of log.warning()
- Debug level is more appropriate for internal force_push diagnostic messages
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.
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.
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
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.
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.
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.
Remove custom deduction guides for std::unique_ptr in C++17 mode.
Issue: FreeBSD GCC 13.3 correctly rejects adding deduction guides
to namespace std, which violates C++ standard [namespace.std]:
"The behavior of a C++ program is undefined if it adds declarations
or definitions to namespace std or to a namespace within namespace std."
Root cause: The code attempted to add custom deduction guides for
std::unique_ptr in namespace std when compiling in C++17 mode.
This is not allowed by the C++ standard.
Solution: Remove the custom deduction guides for C++17 and later,
as the C++17 standard library already provides deduction guides
for std::unique_ptr (added in C++17 via P0433R2).
The custom deduction guide wrappers in the else branch (for C++14
and earlier) are kept as they provide helper functions, not actual
deduction guides in namespace std.
Tested-on: FreeBSD 15 with GCC 13.3
Fixes: Compilation error 'deduction guide must be declared in the
same scope as template std::unique_ptr'
This commit addresses the test failures reported in issue #156
on FreeBSD platform.
1. Fix POSIX semaphore naming for FreeBSD compatibility
- FreeBSD requires semaphore names to start with "/"
- Add "_sem" suffix to avoid namespace conflicts with shm
- Store semaphore name separately for proper cleanup
- This fixes all 24 semaphore test failures
2. Fix robust mutex EOWNERDEAD handling
- When pthread_mutex_lock returns EOWNERDEAD, the lock is
already acquired by the calling thread
- After calling pthread_mutex_consistent(), we should return
success immediately, not unlock and retry
- Previous behavior caused issues with FreeBSD's libthr robust
mutex list management, leading to fatal errors
- This fixes the random crashes in MutexTest
Technical details:
- EOWNERDEAD indicates the previous lock owner died while holding
the lock, but the current thread has successfully acquired it
- pthread_mutex_consistent() restores the mutex to a consistent state
- The Linux implementation worked differently, but the new approach
is more correct according to POSIX semantics and works on both
Linux and FreeBSD
Fixes#156