Re: How to properly exit a thread?
- From: Paul Davis <pjdavis engineering uiowa edu>
- Cc: gtkmm-list gnome org
- Subject: Re: How to properly exit a thread?
- Date: Sun, 14 May 2006 01:42:48 -0500
Sorry, for the quick repost, but I got curious and checked the source
for Glib::Thread.
Unless I'm missing something, this looks to be the bit of importance:
File: glibmm/glib/src/thread.ccg
try
{
// Recreate the specific slot, and drop the reference obtained by
create().
(*static_cast<sigc::slot<void>*>(slot))();
}
catch(Glib::Thread::Exit&)
{
// Just exit from the thread. The Thread::Exit exception
// is our sane C++ replacement of g_thread_exit().
}
catch(...)
{
Glib::exception_handlers_invoke();
}
And a note of interest in the docs:
http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1Thread.html#_details
g_thread_exit() is not wrapped, because that function exits a thread
without any cleanup. That's especially dangerous in C++ code, since the
destructors of automatic objects won't be invoked. Instead, you can
throw a Thread::Exit
<http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1Thread_1_1Exit.html>
exception, which will be caught by the internal thread entry function.
So, this is what I've come up with. To me, the Glib::Thread::Exit seems
to not really do a whole lot. Well, I suppose if you have some
complicated thread working, and you're something like four levels down
in different method calls, you could exit the thread by throwing this
error and letting the stack unwind. Now, I've got mixed feelings on
such a design, but it seems fairly much a design issue and not an API
issue. Ie, if someone wanted to do something like this, they should
implement it themselves. But I do realize its a grey area, and someone's
probably got a better reason than what I came up with for having it.
And, I'm fairly intrigued about the notes about destructors not
automatically being cleaned up after calling g_thread_exit().
Interesting find: In Stroustrup's book "The C++ Programing Language 3rd
Edition" there's coverage of calling exit() (similar case to
g_thread_exit() ) in Section 9.4.1.1 on page 218. Of specific interest,
quoting: "Calling exit() means that the local variables of the calling
function and its callers will not have their destructors invoked."
I never knew this. Kinda makes you scratch your head and think.
Anyway, armed with my new knowledge that such conditions are "in the
book" I'd think just not wrapping g_thread_exit would've been enough.
But Glib::Thread:Exit adds some convenience to do things I wouldn't
necessarily do myself.
So it would seem, functions like exit(), or g_thread_exit() don't allow
destructors to be called because scope doesn't pass back out of the
calling methods, and as a consequence, local variables don't get popped
off the stack which in turn prevents normal destruction...
Cool.
Oh, and my earlier note about not calling return in your read_new_data()
was incorrect. Unless I'm missing something, the only thing you can't do
is call a non-returning function (g_thread_exit() ).
Oh, and to answer the original question:
throw Glib::Thread::Exit() ;
anywhere in the slot you pass to Glib::Thread::Create
(FrameNode::read_new_data() ) is how you exit the thread.
Paul
Paul Davis wrote:
Xiangfei,
Docs indicate doing something like this:
void
FrameNode::read_new_data()
{
bool done = false ;
while( !done )
{
[do something]
}
throw Glib::Thread::Exit() ;
}
(Although, as a side note, and without looking at the Glib::Thread
code and basing everything off of my guess as to how this is
implemented, throw Glib::Thread::Exit() is optional at the end, and is
probably meant as a way to exit the thread "early". Ie, don't call
return ; Maybe someone with more experience on the Glib::Thread
implementation coudl explain this a bit better, because it seems like
an odd choice of implementation to me.)
What you've probably got at issue is guranteeing that all of your
threads have exited before you attempt to close your program. My
guess is that you've got a thread waiting on a condtion variable when
an attempt to destroy the condition variable is made.
Without any more info on what your thread is doing, I can't really say
much else.
As a side note, if you create your thread as joinable, read->join()
will block until the thread exits. If you need to ensure that a
thread has exited at some point in your software, this would be one
method of doing so. (This is making some assumptions, like the spawned
thread was required to finish before the spawning thread, if that
makes any sense.) The more general method is using one of the normal
synchronization constructs. Ie, a semaphore.
Hope that helps more than it confuses.
Paul
Xiangfei Jia wrote:
I created a thread like this:
Glib::Thread *const read =
Glib::Thread::create(sigc::mem_fun(node, &FrameNode::read_new_data),
false);
Sometimes, when I exit from my program I got this error message:
GThread-ERROR **: file gthread-posix.c: line 247 (): error 'Device or
resource busy' during 'pthread_cond_destroy ((pthread_cond_t *) cond)'
aborting...
Aborted
I looked at the Glib reference, I found out I should use
throw Glib::Thread::Exit
<http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1Thread_1_1Exit.html>
();
to exit my thread. But I don't really know how to use this properly.
Can anyone tell me how to use it please!!!!!
Thanks in advance!
Fei
------------------------------------------------------------------------
_______________________________________________
gtkmm-list mailing list
gtkmm-list gnome org
http://mail.gnome.org/mailman/listinfo/gtkmm-list
_______________________________________________
gtkmm-list mailing list
gtkmm-list gnome org
http://mail.gnome.org/mailman/listinfo/gtkmm-list
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]