Skip to content

Commit addfe4f

Browse files
authored
Merge pull request #161 from mutouyun/fix/freebsd-mutex-unlock-timing
Fix mutex unlock timing for FreeBSD multi-run stability
2 parents 0ba1214 + 2593213 commit addfe4f

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

src/libipc/platform/posix/mutex.h

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,21 +150,19 @@ class mutex {
150150

151151
void close() noexcept {
152152
if ((ref_ != nullptr) && (shm_ != nullptr) && (mutex_ != nullptr)) {
153-
// Try to unlock the mutex before destroying it.
154-
// This is important for robust mutexes on FreeBSD, which maintain
155-
// a per-thread robust list. If we destroy a mutex while it's in
156-
// the robust list (even if not locked), FreeBSD may encounter
157-
// dangling pointers later, leading to segfaults.
158-
// We ignore any errors from unlock() since:
159-
// 1. If we don't hold the lock, EPERM is expected and harmless
160-
// 2. If the mutex is already unlocked, this is a no-op
161-
// 3. If there's an error, we still want to proceed with cleanup
162-
::pthread_mutex_unlock(mutex_);
163-
164153
if (shm_->name() != nullptr) {
165154
release_mutex(shm_->name(), [this] {
166155
auto self_ref = ref_->fetch_sub(1, std::memory_order_relaxed);
167156
if ((shm_->ref() <= 1) && (self_ref <= 1)) {
157+
// Before destroying the mutex, try to unlock it.
158+
// This is important for robust mutexes on FreeBSD, which maintain
159+
// a per-thread robust list. If we destroy a mutex while it's locked
160+
// or still in the robust list, FreeBSD may encounter dangling pointers
161+
// later, leading to segfaults.
162+
// Only unlock here (when we're the last reference) to avoid
163+
// interfering with other threads that might be using the mutex.
164+
::pthread_mutex_unlock(mutex_);
165+
168166
int eno;
169167
if ((eno = ::pthread_mutex_destroy(mutex_)) != 0) {
170168
ipc::error("fail pthread_mutex_destroy[%d]\n", eno);
@@ -182,11 +180,11 @@ class mutex {
182180

183181
void clear() noexcept {
184182
if ((shm_ != nullptr) && (mutex_ != nullptr)) {
185-
// Try to unlock before destroying, same reasoning as in close()
186-
::pthread_mutex_unlock(mutex_);
187-
188183
if (shm_->name() != nullptr) {
189184
release_mutex(shm_->name(), [this] {
185+
// Unlock before destroying, same reasoning as in close()
186+
::pthread_mutex_unlock(mutex_);
187+
190188
int eno;
191189
if ((eno = ::pthread_mutex_destroy(mutex_)) != 0) {
192190
ipc::error("fail pthread_mutex_destroy[%d]\n", eno);

src/libipc/platform/posix/shm_posix.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,10 @@ std::int32_t release(id_t id) noexcept {
173173
else if ((ret = acc_of(ii->mem_, ii->size_).fetch_sub(1, std::memory_order_acq_rel)) <= 1) {
174174
::munmap(ii->mem_, ii->size_);
175175
if (!ii->name_.empty()) {
176-
::shm_unlink(ii->name_.c_str());
176+
int unlink_ret = ::shm_unlink(ii->name_.c_str());
177+
if (unlink_ret == -1) {
178+
ipc::error("fail shm_unlink[%d]: %s\n", errno, ii->name_.c_str());
179+
}
177180
}
178181
}
179182
else ::munmap(ii->mem_, ii->size_);
@@ -190,7 +193,10 @@ void remove(id_t id) noexcept {
190193
auto name = std::move(ii->name_);
191194
release(id);
192195
if (!name.empty()) {
193-
::shm_unlink(name.c_str());
196+
int unlink_ret = ::shm_unlink(name.c_str());
197+
if (unlink_ret == -1) {
198+
ipc::error("fail shm_unlink[%d]: %s\n", errno, name.c_str());
199+
}
194200
}
195201
}
196202

@@ -199,7 +205,12 @@ void remove(char const * name) noexcept {
199205
ipc::error("fail remove: name is empty\n");
200206
return;
201207
}
202-
::shm_unlink(name);
208+
// For portable use, a shared memory object should be identified by name of the form /somename.
209+
ipc::string op_name = ipc::string{"/"} + name;
210+
int unlink_ret = ::shm_unlink(op_name.c_str());
211+
if (unlink_ret == -1) {
212+
ipc::error("fail shm_unlink[%d]: %s\n", errno, op_name.c_str());
213+
}
203214
}
204215

205216
} // namespace shm

0 commit comments

Comments
 (0)