Skip to content

Commit 47fa303

Browse files
committed
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.
1 parent a82e3fa commit 47fa303

File tree

1 file changed

+8
-12
lines changed

1 file changed

+8
-12
lines changed

src/libipc/platform/posix/mutex.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -206,19 +206,15 @@ class mutex {
206206
case ETIMEDOUT:
207207
return false;
208208
case EOWNERDEAD: {
209-
if (shm_->ref() > 1) {
210-
shm_->sub_ref();
211-
}
209+
// EOWNERDEAD means we have successfully acquired the lock,
210+
// but the previous owner died. We need to make it consistent.
212211
int eno2 = ::pthread_mutex_consistent(mutex_);
213212
if (eno2 != 0) {
214213
ipc::error("fail pthread_mutex_lock[%d], pthread_mutex_consistent[%d]\n", eno, eno2);
215214
return false;
216215
}
217-
// EOWNERDEAD means we have successfully acquired the lock,
218-
// but the previous owner died. After calling pthread_mutex_consistent(),
219-
// the mutex is now in a consistent state and we hold the lock.
220-
// We should return success here, not unlock and retry.
221-
// This avoids issues with FreeBSD's robust mutex list management.
216+
// After calling pthread_mutex_consistent(), the mutex is now in a
217+
// consistent state and we hold the lock. Return success.
222218
return true;
223219
}
224220
default:
@@ -238,15 +234,15 @@ class mutex {
238234
case ETIMEDOUT:
239235
return false;
240236
case EOWNERDEAD: {
241-
if (shm_->ref() > 1) {
242-
shm_->sub_ref();
243-
}
237+
// EOWNERDEAD means we have successfully acquired the lock,
238+
// but the previous owner died. We need to make it consistent.
244239
int eno2 = ::pthread_mutex_consistent(mutex_);
245240
if (eno2 != 0) {
246241
ipc::error("fail pthread_mutex_timedlock[%d], pthread_mutex_consistent[%d]\n", eno, eno2);
247242
throw std::system_error{eno2, std::system_category()};
248243
}
249-
// Successfully acquired the lock after making it consistent
244+
// After calling pthread_mutex_consistent(), the mutex is now in a
245+
// consistent state and we hold the lock. Return success.
250246
return true;
251247
}
252248
default:

0 commit comments

Comments
 (0)