apache/hadoop · error
mutexLock: pthread_mutex_lock failed with error %d
Error message
mutexLock: pthread_mutex_lock failed with error %d
What it means
mutexLock() is libhdfs' wrapper around pthread_mutex_lock; it prints this when the call returns an error instead of blocking: EINVAL (mutex storage not initialized or corrupted), EDEADLK (thread already owns this non-recursive mutex), or EAGAIN (recursion limit on a recursive mutex). The wrapper still returns the error, so callers continue without mutual exclusion held — a correctness hazard beyond the log line.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfs/os/posix/mutexes.c:37
#include "os/mutexes.h"
#include <pthread.h>
#include <stdio.h>
mutex jvmMutex;
mutex jclassInitMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutexattr_t jvmMutexAttr;
__attribute__((constructor)) static void init() {
pthread_mutexattr_init(&jvmMutexAttr);
pthread_mutexattr_settype(&jvmMutexAttr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&jvmMutex, &jvmMutexAttr);
}
int mutexLock(mutex *m) {
int ret = pthread_mutex_lock(m);
if (ret) {
fprintf(stderr, "mutexLock: pthread_mutex_lock failed with error %d\n",
ret);
}
return ret;
}
int mutexUnlock(mutex *m) {
int ret = pthread_mutex_unlock(m);
if (ret) {
fprintf(stderr, "mutexUnlock: pthread_mutex_unlock failed with error %d\n",
ret);
}
return ret;
}
View on GitHub (pinned to 2add963021)
Solutions
- Map the number: EINVAL means uninitialized/corrupted mutex — hunt overruns near the storage with ASan/valgrind; EDEADLK means recursive locking of a non-recursive mutex — restructure the call path
- Never call libhdfs APIs re-entrantly from callbacks or signal handlers on a thread that is already inside an HDFS call
- If it appears at startup with odd behavior, assume corruption until proven otherwise
- Rebuild/upgrade libhdfs if a build-specific init-ordering bug is suspected
Example fix
/* before */
mutexLock(&m);
/* proceeds even when the lock failed */
/* after */
if (mutexLock(&m) != 0) {
return -1; /* lock NOT held — bail instead of running unsynchronized */
}
/* ... */
mutexUnlock(&m); Defensive patterns
Strategy: validation
Try / catch
/* when hacking on libhdfs internals: never ignore the wrapper return */
if (mutexLock(&m) != 0) {
return -1; /* lock NOT held — do not proceed */
}
/* critical section */
mutexUnlock(&m); Prevention
- Treat any pthread mutex error as a corruption smoke signal until proven otherwise
- Never call libhdfs re-entrantly from callbacks or signal handlers on the same thread
- Keep app and libhdfs on matching glibc/pthread versions
When it happens
Trigger: Recursive locking of jclassInitMutex (a plain PTHREAD_MUTEX_INITIALIZER, non-recursive) from the same thread; a mutex whose storage was reinitialized or overwritten; exceeding recursive depth on jvmMutex (initialized PTHREAD_MUTEX_RECURSIVE by the library constructor).
Common situations: Re-entrant call paths through libhdfs from callbacks; heap/stack corruption smashing static mutex storage (EINVAL plus unrelated crashes); unusual static-link or dlopen ordering where the constructor init of jvmMutexAttr never ran.
Related errors
- mutexUnlock: pthread_mutex_unlock failed with error %d
- threadCreate: pthread_create failed with error %d
- threadJoin: pthread_join failed with error %d
- threadLocalStorageGet: pthread_key_create failed with error
- threadLocalStorageSet: pthread_setspecific failed with error
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/93a51501848226f3.
Report an issue: GitHub.