From e66bd880e98d69aeb327cacb38db39e293f54492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Sun, 30 Nov 2025 07:00:32 +0000 Subject: [PATCH] fix(platform): resolve ODR violation in make_timespec/calc_wait_time inline functions Problem: - Both linux/get_wait_time.h and posix/get_wait_time.h define inline functions make_timespec() and calc_wait_time() in namespace ipc::detail - On Linux, semaphore uses posix implementation, but may include both headers - This causes ODR (One Definition Rule) violation - undefined behavior - Different inline function definitions with same name violates C++ standard - Manifested as test failures in SemaphoreTest::WaitTimeout Solution: - Add platform-specific namespace layer between ipc and detail: - linux/get_wait_time.h: ipc::linux::detail::make_timespec() - posix/get_wait_time.h: ipc::posix::detail::make_timespec() - Update all call sites to use fully qualified names: - linux/condition.h: linux::detail::make_timespec() - linux/mutex.h: linux::detail::make_timespec() (2 places) - posix/condition.h: posix::detail::make_timespec() - posix/mutex.h: posix::detail::make_timespec() (2 places) - posix/semaphore_impl.h: posix::detail::make_timespec() This ensures each platform's implementation is uniquely named, preventing ODR violations and ensuring correct function resolution at compile time. --- src/libipc/platform/linux/condition.h | 2 +- src/libipc/platform/linux/get_wait_time.h | 2 ++ src/libipc/platform/linux/mutex.h | 4 ++-- src/libipc/platform/posix/condition.h | 2 +- src/libipc/platform/posix/get_wait_time.h | 2 ++ src/libipc/platform/posix/mutex.h | 4 ++-- src/libipc/platform/posix/semaphore_impl.h | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libipc/platform/linux/condition.h b/src/libipc/platform/linux/condition.h index c4f00ca..d5f195a 100644 --- a/src/libipc/platform/linux/condition.h +++ b/src/libipc/platform/linux/condition.h @@ -27,7 +27,7 @@ public: return false; } } else { - auto ts = detail::make_timespec(tm); + auto ts = linux::detail::make_timespec(tm); int eno = A0_SYSERR(a0_cnd_timedwait(native(), static_cast(mtx.native()), {ts})); if (eno != 0) { if (eno != ETIMEDOUT) { diff --git a/src/libipc/platform/linux/get_wait_time.h b/src/libipc/platform/linux/get_wait_time.h index ffaf2d2..e8fc01e 100644 --- a/src/libipc/platform/linux/get_wait_time.h +++ b/src/libipc/platform/linux/get_wait_time.h @@ -10,6 +10,7 @@ #include "a0/err_macro.h" namespace ipc { +namespace linux { namespace detail { inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept { @@ -43,4 +44,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) { } } // namespace detail +} // namespace linux } // namespace ipc diff --git a/src/libipc/platform/linux/mutex.h b/src/libipc/platform/linux/mutex.h index 8fd84d5..facad76 100644 --- a/src/libipc/platform/linux/mutex.h +++ b/src/libipc/platform/linux/mutex.h @@ -25,7 +25,7 @@ public: bool lock(std::uint64_t tm) noexcept { if (!valid()) return false; for (;;) { - auto ts = detail::make_timespec(tm); + auto ts = linux::detail::make_timespec(tm); int eno = A0_SYSERR( (tm == invalid_value) ? a0_mtx_lock(native()) : a0_mtx_timedlock(native(), {ts})); @@ -56,7 +56,7 @@ public: bool try_lock() noexcept(false) { if (!valid()) return false; - int eno = A0_SYSERR(a0_mtx_timedlock(native(), {detail::make_timespec(0)})); + int eno = A0_SYSERR(a0_mtx_timedlock(native(), {linux::detail::make_timespec(0)})); switch (eno) { case 0: return true; diff --git a/src/libipc/platform/posix/condition.h b/src/libipc/platform/posix/condition.h index 521f9fe..968f716 100644 --- a/src/libipc/platform/posix/condition.h +++ b/src/libipc/platform/posix/condition.h @@ -115,7 +115,7 @@ public: } break; default: { - auto ts = detail::make_timespec(tm); + auto ts = posix::detail::make_timespec(tm); int eno; if ((eno = ::pthread_cond_timedwait(cond_, static_cast(mtx.native()), &ts)) != 0) { if (eno != ETIMEDOUT) { diff --git a/src/libipc/platform/posix/get_wait_time.h b/src/libipc/platform/posix/get_wait_time.h index 785cd75..94f9565 100644 --- a/src/libipc/platform/posix/get_wait_time.h +++ b/src/libipc/platform/posix/get_wait_time.h @@ -10,6 +10,7 @@ #include "libipc/utility/log.h" namespace ipc { +namespace posix { namespace detail { inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept { @@ -36,4 +37,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) { } } // namespace detail +} // namespace posix } // namespace ipc diff --git a/src/libipc/platform/posix/mutex.h b/src/libipc/platform/posix/mutex.h index d84736f..1d3baf8 100644 --- a/src/libipc/platform/posix/mutex.h +++ b/src/libipc/platform/posix/mutex.h @@ -196,7 +196,7 @@ public: bool lock(std::uint64_t tm) noexcept { if (!valid()) return false; for (;;) { - auto ts = detail::make_timespec(tm); + auto ts = posix::detail::make_timespec(tm); int eno = (tm == invalid_value) ? ::pthread_mutex_lock(mutex_) : ::pthread_mutex_timedlock(mutex_, &ts); @@ -230,7 +230,7 @@ public: bool try_lock() noexcept(false) { if (!valid()) return false; - auto ts = detail::make_timespec(0); + auto ts = posix::detail::make_timespec(0); int eno = ::pthread_mutex_timedlock(mutex_, &ts); switch (eno) { case 0: diff --git a/src/libipc/platform/posix/semaphore_impl.h b/src/libipc/platform/posix/semaphore_impl.h index 0a33349..c239dba 100644 --- a/src/libipc/platform/posix/semaphore_impl.h +++ b/src/libipc/platform/posix/semaphore_impl.h @@ -88,7 +88,7 @@ public: return false; } } else { - auto ts = detail::make_timespec(tm); + auto ts = posix::detail::make_timespec(tm); if (::sem_timedwait(h_, &ts) != 0) { if (errno != ETIMEDOUT) { ipc::error("fail sem_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",