mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 19:01:56 -04:00
The old macro expanded to two statements (mutex_lock + DEFER unlock). In an unbraced if/else only the lock would be conditional while the DEFER always executed — a latent double-unlock / unbalanced-unlock bug. Add ScopedMutexLock to both debug and ndebug headers: - debug: stores __FILE__/__func__/__LINE__ from the call site and passes them to _mutex_lock/_mutex_unlock for diagnostics - ndebug: lightweight wrapper around mutex_lock/mutex_unlock Redefine mutex_lockguard to create a single uniquely-named ScopedMutexLock variable (via __COUNTER__), making it safe in any statement context. Remove the now-unused scope_guard include. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
85 lines
1.2 KiB
C++
85 lines
1.2 KiB
C++
#pragma once
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <pthread.h>
|
|
|
|
#ifndef PTHREAD_MUTEX_ADAPTIVE_NP
|
|
# define PTHREAD_MUTEX_ADAPTIVE_NP PTHREAD_MUTEX_NORMAL
|
|
#endif
|
|
|
|
|
|
static
|
|
inline
|
|
void
|
|
mutex_init(pthread_mutex_t &mutex_)
|
|
{
|
|
int rv;
|
|
pthread_mutexattr_t attr;
|
|
|
|
pthread_mutexattr_init(&attr);
|
|
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ADAPTIVE_NP);
|
|
|
|
rv = pthread_mutex_init(&mutex_,&attr);
|
|
if(rv != 0)
|
|
std::abort();
|
|
|
|
pthread_mutexattr_destroy(&attr);
|
|
}
|
|
|
|
static
|
|
inline
|
|
void
|
|
mutex_lock(pthread_mutex_t &mutex_)
|
|
{
|
|
int rv;
|
|
|
|
rv = pthread_mutex_lock(&mutex_);
|
|
if(rv != 0)
|
|
std::abort();
|
|
}
|
|
|
|
static
|
|
inline
|
|
void
|
|
mutex_unlock(pthread_mutex_t &mutex_)
|
|
{
|
|
int rv;
|
|
|
|
rv = pthread_mutex_unlock(&mutex_);
|
|
if(rv != 0)
|
|
std::abort();
|
|
}
|
|
|
|
static
|
|
inline
|
|
void
|
|
mutex_destroy(pthread_mutex_t &mutex_)
|
|
{
|
|
int rv;
|
|
|
|
rv = pthread_mutex_destroy(&mutex_);
|
|
if(rv != 0)
|
|
std::abort();
|
|
}
|
|
|
|
class ScopedMutexLock
|
|
{
|
|
private:
|
|
pthread_mutex_t &_mutex;
|
|
|
|
public:
|
|
ScopedMutexLock(pthread_mutex_t &mutex_)
|
|
: _mutex(mutex_)
|
|
{
|
|
mutex_lock(_mutex);
|
|
}
|
|
|
|
~ScopedMutexLock()
|
|
{
|
|
mutex_unlock(_mutex);
|
|
}
|
|
|
|
ScopedMutexLock(const ScopedMutexLock&) = delete;
|
|
ScopedMutexLock& operator=(const ScopedMutexLock&) = delete;
|
|
};
|