Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pthread_mutex_destroy

184 views
Skip to first unread message

Kostas Kostiadis

unread,
Mar 18, 1999, 3:00:00 AM3/18/99
to
Hello,

I have a set of simple questions...Please help.

1) What happens if a thread tries to lock a
mutex that has been destroyed??? (Does
pthread_mutex_lock() return a specific
error code?)

2) What happens if a thread successfully locks
a mutex and then another thread destroys that
mutex before the first thread unlocks???

3) Do the same things apply for destroying a
condition variable???

4) Is it safer to lock a mutex and then destroy it???
But if you do that, can you then unlock it??? Or you
don't need to unlock it since it has been destroyed...

Thanx in advance,
Kostas.

David McCann

unread,
Mar 18, 1999, 3:00:00 AM3/18/99
to
Kostas Kostiadis wrote:

> Hello,
>
> I have a set of simple questions...Please help

In essence, the answer is "undefined". On some implementations
you may receive EFAULT, EINVAL or suchlike when you try to
use a synchronization variable you've just destroyed, and likewise
you may get EBUSY if you try to destroy a locked mutex or
whatever, but in general you cannot rely on this behaviour.
The most likely outcome is a nice big SIGSEGV, IMHO.

Hope this helps,

David McCann.

Wolfgang Bartelt

unread,
Mar 18, 1999, 3:00:00 AM3/18/99
to
I've come across this problem with SuSE 6.0 (Kernel 2.0.36) and
I thought I better lock the mutex before I destroy it in a somewhat
controlled manner. The result was errno=EBUSY, leaving me no other
choice than to unlock the mutex and pray() and then destroy the
mutex... but then I understood ... all you have to do to prevent disaster
is checking the return value of pthread_mutex_*() everywhere (and I mean
it), so just forget about all the bad thread programming examples on the
net. If you follow this path all is just a question of how to get rid of
this thing,
maybe by a sequence like this

if(!(error = pthread_mutex_lock(...))) {
if(!(error = pthread_mutex_destroy(...))) {
printf("It's my lucky day...\n") ;
....
}
switch(error) { /* couldn't destroy the locked mutex */
...
case EBUSY: /* That can only be me */
if(!(error = pthread_mutex_unlock(...))) {
while(error = pthread_mutex_destroy(...)) {
printf("This may be going on for ever...\n") ;
switch(error) {
....
case EBUSY: ..... continue ; /* bloody hell, how is
using it now ?? */
case EINVAL: printf("Somebody killed it already?")
;
....
}
}
printf("finally dead...\n") ;
} else if(error = EINVAL)
printf("Somebody killed that bloody thing without having it
locked???\n") ;
..........
.......... etc. etc.

Isn't that fun ? I reckon NO.

Wolfgang Bartelt

David McCann wrote in message <36F0C758...@no-spam.com>...

Kaz Kylheku

unread,
Mar 20, 1999, 3:00:00 AM3/20/99
to
On Thu, 18 Mar 1999 01:02:04 -0000, Kostas Kostiadis <kko...@essex.ac.uk> wrote:
>Hello,
>
>I have a set of simple questions...Please help.
>
>1) What happens if a thread tries to lock a
>mutex that has been destroyed??? (Does
>pthread_mutex_lock() return a specific
>error code?)

This is simply undefined behavior. It's sort of like using a C++ object whose
destructor has already been called, or using a pointer to an automatic
object whose enclosing statement block has terminated.

>2) What happens if a thread successfully locks
>a mutex and then another thread destroys that
>mutex before the first thread unlocks???

Then pthread_mutex_destroy() should return EBUSY. But this is more of a fool's
error code; a properly written program won't be destroying objects that are
still in use by another thread!

As a rule of thumb, when any object is destroyed, the thread which is doing the
destruction should be the only remaining ``owner'' of that object.

Once the object is destroyed, its value is indeterminate, so it's impossible
to tell anything from its value. If threads continue to use the object, the
behavior is unpredictable.

There are various ways to ensure that only one thread performs the destruction.
One method is reference counting; a thread which removes the last reference
count from a dynamic object will destroy it and release its memory.

There are other ways of course; for eaxmple, an active object may be destroyed
after its internal threads have been shut down, and it's known that no other
threads will enter the object from the outside. This is known as ``orderly
shutdown''.

>3) Do the same things apply for destroying a
>condition variable???

In this respect, mutexes and condition variables should be treated like any
other shared objects in your program.

>4) Is it safer to lock a mutex and then destroy it???

A mutex should be unlocked prior to destruction, so that pthread_mutex_destroy
does not fail with EBUSY.

>But if you do that, can you then unlock it??? Or you
>don't need to unlock it since it has been destroyed...

Once it's destroyed, it's no longer a mutex, but just a piece of memory having
indeterminate contents. Any use of such memory other than initializing it again
should be viewed as an error.

If you try to lock or unlock a destroyed mutex, your program could crash, or
the calling thread could hang, etc.

Kaz Kylheku

unread,
Mar 20, 1999, 3:00:00 AM3/20/99
to
On Thu, 18 Mar 1999 23:20:42 +1000, Wolfgang Bartelt
<Wolfgang...@ticom.com.au> wrote:
>I've come across this problem with SuSE 6.0 (Kernel 2.0.36) and
>I thought I better lock the mutex before I destroy it in a somewhat
>controlled manner. The result was errno=EBUSY, leaving me no other

If you read the LinuxThreads manual page for pthread_mutex_lock, you could have
found this out the easy way. Doesn't the SuSE distribution offer these pages?

>choice than to unlock the mutex and pray() and then destroy the

Why would you pray after unlocking the mutex? What are you trying to achieve
by locking the mutex before destroying it?

If other threads are still using the mutex when you are about to destroy it,
locking the mutex won't help, and neither will prayer.

>mutex... but then I understood ... all you have to do to prevent disaster
>is checking the return value of pthread_mutex_*() everywhere (and I mean
>it), so just forget about all the bad thread programming examples on the
>net. If you follow this path all is just a question of how to get rid of
>this thing,
>maybe by a sequence like this
>
>if(!(error = pthread_mutex_lock(...))) {
> if(!(error = pthread_mutex_destroy(...))) {
> printf("It's my lucky day...\n") ;
> ....
> }

This sort of checking should be the subject of assertions that are removed in a
release version of the software. A correctly written program doesn't need to
test these return values; they are only useful for debugging purposes at best.

What you can do is wrap up mutexes behind some other interface which hides
the error checking assertions, so that you don't proliferate mutex-checking
code throughout your project.

In Linux, you can create an ``error checking mutex'' using the initializer
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP. The NP stands for non portable,
because this is a non-portable extension. These should only be used for
debugging.

Wolfgang Bartelt

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to

Kaz Kylheku wrote in message ...

>On Thu, 18 Mar 1999 23:20:42 +1000, Wolfgang Bartelt
><Wolfgang...@ticom.com.au> wrote:
>>I've come across this problem with SuSE 6.0 (Kernel 2.0.36) and
>>I thought I better lock the mutex before I destroy it in a somewhat
>>controlled manner. The result was errno=EBUSY, leaving me no other
>
>If you read the LinuxThreads manual page for pthread_mutex_lock, you could
have
>found this out the easy way. Doesn't the SuSE distribution offer these
pages?
>

You're right, I couldn't yet locate the pthread documentation in the massive
5 CD distribution and it's an item on my worklist to find the stuff soon. In
the
meantime I helped myself with Sun's online docu which says that EBUSY
is not a valid return value for pthread_mutex_destroy(). Hence my
surprise...

>>choice than to unlock the mutex and pray() and then destroy the
>
>Why would you pray after unlocking the mutex? What are you trying to
achieve
>by locking the mutex before destroying it?
>
>If other threads are still using the mutex when you are about to destroy
it,
>locking the mutex won't help, and neither will prayer.
>

Come on, that's not so difficult to imagine, Kaz. I had dynamically
allocated
a structure which contained its mutex lock as one of its components. This
data structure was shared among multiple threads. So, to deallocate this
data structure you have to lock the mutex, then destroy the mutex and then
to
free the memory buffer. In a multi-threaded environment you can't obviously
free the memory buffer first as you may know(which would be bad programming
practice anyway). That was my theory when I started thsi exercise.

Now, for using my data structures with pthreads under Linux I now had to
lock
the mutex, set a flag to prevent other threads from accessing the buffer and
then
unlock(!) the mutex again and then destroy the mutex. Calling
pthread_mutex_destroy()
may now fail for various reasons and makes mutex destruction really much
more
complicated. That's what I referred to in my program example.
The prayer is, of course, an optional implementation feature. Anyway, in my
opinion the EBUSY return value for pthread_mutex_destroy() under Linux is
more a bug than a feature...

>>mutex... but then I understood ... all you have to do to prevent disaster
>>is checking the return value of pthread_mutex_*() everywhere (and I mean
>>it), so just forget about all the bad thread programming examples on the
>>net. If you follow this path all is just a question of how to get rid of
>>this thing,
>>maybe by a sequence like this
>>
>>if(!(error = pthread_mutex_lock(...))) {
>> if(!(error = pthread_mutex_destroy(...))) {
>> printf("It's my lucky day...\n") ;
>> ....
>> }
>
>This sort of checking should be the subject of assertions that are removed
in a
>release version of the software. A correctly written program doesn't need
to
>test these return values; they are only useful for debugging purposes at
best.
>

I have proven you wrong...

>What you can do is wrap up mutexes behind some other interface which hides
>the error checking assertions, so that you don't proliferate mutex-checking
>code throughout your project.
>

That's what I do anyway and everybody else who does serious programming. But
that was not the issue here.

>In Linux, you can create an ``error checking mutex'' using the initializer
>PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP. The NP stands for non portable,
>because this is a non-portable extension. These should only be used for
>debugging.

Thanks for the hint. I really have to find this bloody documentation on
these CDs.

Xavier Leroy

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to

"Wolfgang Bartelt" <Wolfgang...@ticom.com.au> writes:

> Anyway, in my
> opinion the EBUSY return value for pthread_mutex_destroy() under Linux is
> more a bug than a feature...

It's mandated by the POSIX standard, so you'll have to live with it.

You may be happy to learn that, in LinuxThreads, pthread_mutex_destroy()
does nothing because a mutex doesn't consume any resources in addition to
the memory space where it's stored. So, whether you call
pthread_mutex_destroy() at all will not make any difference. Of course,
other implementations of POSIX threads work differently, so
if you want your code to be portable, you must use pthread_mutex_destroy().

> Come on, that's not so difficult to imagine, Kaz. I had dynamically
> allocated
> a structure which contained its mutex lock as one of its components. This
> data structure was shared among multiple threads. So, to deallocate this
> data structure you have to lock the mutex, then destroy the mutex and then
> to
> free the memory buffer. In a multi-threaded environment you can't obviously
> free the memory buffer first as you may know(which would be bad programming
> practice anyway). That was my theory when I started thsi exercise.

Kaz's point still stands: if you deallocate the data structure, that's
because you know that it's no longer used in any of your threads,
so you don't need to lock the mutex before deallocating it.

Deallocating a data structure that other threads might be currently
using or be about to use in the future is a programming error; by
locking the mutex before deallocation, you're not fixing the
programming error at all. I'm not even sure this will help you track
down the error -- tools like Purify, or even better a garbage collector,
would be much more effective.

- Xavier Leroy

--
Valid e-mail address (without the underscores): Xavier.Leroy@i_n_r_i_a.f_r
This is a protection against junk mail. Apologies for the inconvenience.
Home page: http://pauillac.inria.fr/~xleroy/

Kaz Kylheku

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to
On Mon, 22 Mar 1999 15:13:58 +1000, Wolfgang Bartelt
<Wolfgang...@ticom.com.au> wrote:
>Now, for using my data structures with pthreads under Linux I now had to
>lock
>the mutex, set a flag to prevent other threads from accessing the buffer and
>then
>unlock(!) the mutex again and then destroy the mutex. Calling

I think that you may have a bug.

Let's get this straight: you have a flag which is protected by a mutex.
You set the flag, and then destroy the mutex. But how can any thread examine
the flag now? The mutex is gone!

Also, where does this flag live? Surely it's not part of the object being
destroyed? If so, how can the flag be inspected if the object is gone?

I think you may need to implement reference counting or garbage collection.

The basic idea is that before releasing an object's memory, you must ensure
that no threads are using that object (other than the one performing the
freeing oepration).

Bil Lewis

unread,
Mar 22, 1999, 3:00:00 AM3/22/99
to
Kaz is most correct.

If you want to look at some example code which does much of what
you're talking about, look at the set of programs called list_global_lock.c,
list_*.c, etc. on the web page below.

If you want even more detail, then you'll have to buy my book too.
(Ring up another 65 cents, Jocko!)

Good luck,

-Bil

> Let's get this straight: you have a flag which is protected by a mutex.
> You set the flag, and then destroy the mutex. But how can any thread examine
> the flag now? The mutex is gone!
>
> Also, where does this flag live? Surely it's not part of the object being
> destroyed? If so, how can the flag be inspected if the object is gone?
>
> I think you may need to implement reference counting or garbage collection.
>
> The basic idea is that before releasing an object's memory, you must ensure
> that no threads are using that object (other than the one performing the
> freeing oepration).

--
================
B...@LambdaCS.com

http://www.LambdaCS.com
Lambda Computer Science
555 Bryant St. #194
Palo Alto, CA,
94301

Phone/FAX: (650) 328-8952

0 new messages