Red Hat Bugzilla – Bug 113588
NPTL pthread_mutex_destroy return EBUSY even if mutex is not locked...
Last modified: 2007-11-30 17:07:00 EST
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030922
Description of problem:
pthread_mutex_destroy should return EBUSY if the mutex being destroyed
is currently locked.
If ptread_mutex_unlock is called without calling pthread_mutex_lock,
pthread_mutex_destroy in NPTL returns EBUSY.
This scenario can happen in cleanup handlers where a mutex is being
unlocked when a thread exits.
Version-Release number of selected component (if applicable):
glibc-2.3.2-95.6, kernel-2.4.21-4.EL, RHE ES 3.0, gcc-3.2.3-20
Steps to Reproduce:
int main(int argc, char **argv)
if ((status = pthread_mutex_init(&mutt, NULL)) == 0)
call unlock without first locking the mutex
if ((status = pthread_mutex_unlock(&mutt)) == 0)
destroy results in EBUSY...
if ((status = pthread_mutex_destroy(&mutt)) != 0)
char *strErr = strerror_r(status, buf, 256);
fprintf(stderr, "status=%d, Error: %s\n", status, strErr);
2. gcc -o prog prog.c -lpthread
Actual Results: ./prog prints "status=16, Error: Device or resource
Expected Results: Since the mutex was not locked,
pthread_mutex_destroy should have returned 0.
This happens in NPTL.
LinuxThreads returns 0 for the scenario described above.
env LD_ASSUME_KERNEL=2.4.19 prog
does not print the EBUSY error.
I don't see anything wrong about this behaviour.
says clearly that this program has undefined behaviour.
Returning EBUSY from pthread_mutex_destroy on such a mutex is
a conforming behaviour.
You can use PTHREAD_MUTEX_ERRORCHECK mutex if you want to get an
error from pthread_mutex_unlock and not undefined behaviour.
"It shall be safe to destroy an initialized mutex that is unlocked.
Attempting to destroy a locked mutex results in undefined behavior."
In the example, the mutex is not locked.
The implementation has detected an attempt to destroy the object
referenced by mutex while it is locked or referenced (for example,
while being used in a pthread_cond_timedwait() or pthread_cond_wait())
by another thread."
The mutex in the example is neither locked nor referenced by another
thread. EBUSY shouldn't be returned in this case...
That doesn't matter.
Once your program hits undefined behaviour once, the standard doesn't
cover anything in it any more.
The implementation may choose to lock a mutex in pthread_mutex_unlock
called on an unlocked mutex, format your disk or whatever else it decides.
You have put the mutex in an undefined state by incorrectly calling
pthread_mutex_unlock. Anything can happen after that. Stop arguing
that you are so innocent and the bad implementation should help you
poor developer. It's your fault alone, live with the consequences.
If you cannot write correct code, use the error checking mutex type.
The code given to you is a sample for reproducing the case and I am
not arguing anything here. I was just pointing out what the spec
Mutex unlocks are done in cleanup handlers so that an exiting thread,
that hit a cancellation point, doesn't leave it locked. David
Butenhof's book describes this mechanism in detail in Chapter 5 page
Your response here and elsewhere on the web are always rude and
obnoxious. Looks like you get angry when someone points out problems
in your poorly written code!!!
You talk about bad implementation? You should start with NPTL
because any reasonable implementation would have basic checks before
putting a resource in a funny condition.
Your stance is that if the "spec" doesn't say something - do
something crazy (like format your disk - Thanks Jakub...)
POSIX specifically has error checking mutexes which are supposed to
do basic checks while normal mutexes are not required to do them for
Slowing down all conforming code out there because of a few buggy
programs is a bad idea.
BTW: You can also use PTHREAD_MUTEX_RECURSIVE, which is required
similarly to PTHREAD_MUTEX_ERRORCHECK to fail pthread_mutex_unlock
if called on unlocked mutex.
Mutex unlock in cleanup handlers can be written so that you never unlock
an unlocked mutex.
I am not implying that normal mutexes do more error checks in
Getting an EBUSY led us down the path of trying to figure out where we
were destroying a locked mutex when the problem was of a different
nature with an extra pthread_mutex_unlock of an unlocked mutex.
This was the right behavior for a normal mutex but the error code is
In glibc's pthread_mutex_unlock.c, mutex->__data.__nusers becomes
UINT_MAX when decremented from a value of 0 and
pthread_mutex_destroy.c reports an EBUSY because
mutex->__data.__nusers is ! 0.
Would it make sense to prevent mutex->__data.__nusers from being
decremented when it is zero? This way you don't break compliance with
the spec, the error codes will be correct and undefined behaviors will
remain what they are.
This is just a suggestion since our code doesn't rely on this behavior...