From 47fa303455f543577c3b89d89fb5087da272984f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E5=A4=B4=E4=BA=91?= Date: Sat, 6 Dec 2025 06:21:38 +0000 Subject: [PATCH] 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. --- src/libipc/platform/posix/mutex.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/libipc/platform/posix/mutex.h b/src/libipc/platform/posix/mutex.h index ce42929..0df842b 100644 --- a/src/libipc/platform/posix/mutex.h +++ b/src/libipc/platform/posix/mutex.h @@ -206,19 +206,15 @@ public: case ETIMEDOUT: return false; case EOWNERDEAD: { - if (shm_->ref() > 1) { - shm_->sub_ref(); - } + // EOWNERDEAD means we have successfully acquired the lock, + // but the previous owner died. We need to make it consistent. int eno2 = ::pthread_mutex_consistent(mutex_); if (eno2 != 0) { ipc::error("fail pthread_mutex_lock[%d], pthread_mutex_consistent[%d]\n", eno, eno2); 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. + // After calling pthread_mutex_consistent(), the mutex is now in a + // consistent state and we hold the lock. Return success. return true; } default: @@ -238,15 +234,15 @@ public: case ETIMEDOUT: return false; case EOWNERDEAD: { - if (shm_->ref() > 1) { - shm_->sub_ref(); - } + // EOWNERDEAD means we have successfully acquired the lock, + // but the previous owner died. We need to make it consistent. int eno2 = ::pthread_mutex_consistent(mutex_); if (eno2 != 0) { ipc::error("fail pthread_mutex_timedlock[%d], pthread_mutex_consistent[%d]\n", eno, eno2); throw std::system_error{eno2, std::system_category()}; } - // Successfully acquired the lock after making it consistent + // After calling pthread_mutex_consistent(), the mutex is now in a + // consistent state and we hold the lock. Return success. return true; } default: