diff --git a/src/libipc/platform/posix/mutex.h b/src/libipc/platform/posix/mutex.h index 2293678..ce42929 100644 --- a/src/libipc/platform/posix/mutex.h +++ b/src/libipc/platform/posix/mutex.h @@ -214,13 +214,13 @@ public: ipc::error("fail pthread_mutex_lock[%d], pthread_mutex_consistent[%d]\n", eno, eno2); return false; } - int eno3 = ::pthread_mutex_unlock(mutex_); - if (eno3 != 0) { - ipc::error("fail pthread_mutex_lock[%d], pthread_mutex_unlock[%d]\n", eno, eno3); - return false; - } + // EOWNERDEAD means we have successfully acquired the lock, + // but the previous owner died. After calling pthread_mutex_consistent(), + // the mutex is now in a consistent state and we hold the lock. + // We should return success here, not unlock and retry. + // This avoids issues with FreeBSD's robust mutex list management. + return true; } - break; // loop again default: ipc::error("fail pthread_mutex_lock[%d]\n", eno); return false; @@ -244,15 +244,11 @@ public: int eno2 = ::pthread_mutex_consistent(mutex_); if (eno2 != 0) { ipc::error("fail pthread_mutex_timedlock[%d], pthread_mutex_consistent[%d]\n", eno, eno2); - break; - } - int eno3 = ::pthread_mutex_unlock(mutex_); - if (eno3 != 0) { - ipc::error("fail pthread_mutex_timedlock[%d], pthread_mutex_unlock[%d]\n", eno, eno3); - break; + throw std::system_error{eno2, std::system_category()}; } + // Successfully acquired the lock after making it consistent + return true; } - break; default: ipc::error("fail pthread_mutex_timedlock[%d]\n", eno); break; diff --git a/src/libipc/platform/posix/semaphore_impl.h b/src/libipc/platform/posix/semaphore_impl.h index 6d0da71..8d5a1e8 100644 --- a/src/libipc/platform/posix/semaphore_impl.h +++ b/src/libipc/platform/posix/semaphore_impl.h @@ -19,6 +19,7 @@ namespace sync { class semaphore { ipc::shm::handle shm_; sem_t *h_ = SEM_FAILED; + std::string sem_name_; // Store the actual semaphore name used public: semaphore() = default; @@ -38,9 +39,16 @@ public: ipc::error("[open_semaphore] fail shm.acquire: %s\n", name); return false; } - h_ = ::sem_open(name, O_CREAT, 0666, static_cast(count)); + // POSIX semaphore names must start with "/" on some platforms (e.g., FreeBSD) + // Use a separate namespace for semaphores to avoid conflicts with shm + if (name[0] == '/') { + sem_name_ = std::string(name) + "_sem"; + } else { + sem_name_ = std::string("/") + name + "_sem"; + } + h_ = ::sem_open(sem_name_.c_str(), O_CREAT, 0666, static_cast(count)); if (h_ == SEM_FAILED) { - ipc::error("fail sem_open[%d]: %s\n", errno, name); + ipc::error("fail sem_open[%d]: %s\n", errno, sem_name_.c_str()); return false; } return true; @@ -52,14 +60,14 @@ public: ipc::error("fail sem_close[%d]: %s\n", errno); } h_ = SEM_FAILED; - if (shm_.name() != nullptr) { - std::string name = shm_.name(); + if (!sem_name_.empty() && shm_.name() != nullptr) { if (shm_.release() <= 1) { - if (::sem_unlink(name.c_str()) != 0) { - ipc::error("fail sem_unlink[%d]: %s, name: %s\n", errno, name.c_str()); + if (::sem_unlink(sem_name_.c_str()) != 0) { + ipc::error("fail sem_unlink[%d]: %s, name: %s\n", errno, sem_name_.c_str()); } } } + sem_name_.clear(); } void clear() noexcept { @@ -69,14 +77,22 @@ public: } h_ = SEM_FAILED; } - char const *name = shm_.name(); - if (name == nullptr) return; - ::sem_unlink(name); + if (!sem_name_.empty()) { + ::sem_unlink(sem_name_.c_str()); + sem_name_.clear(); + } shm_.clear(); // Make sure the storage is cleaned up. } static void clear_storage(char const *name) noexcept { - ::sem_unlink(name); + // Construct the semaphore name same way as open() does + std::string sem_name; + if (name[0] == '/') { + sem_name = std::string(name) + "_sem"; + } else { + sem_name = std::string("/") + name + "_sem"; + } + ::sem_unlink(sem_name.c_str()); ipc::shm::handle::clear_storage(name); }