Re: problem with exiting from a Glib::Thread



On Saturday 25 June 2005 12:58, Yair Hershkovitz wrote:
> i call "throw Glib::Thread::Exit()" to exit from a thread,
>
> what happens is:
>
>
> glibmm-ERROR **:
> unhandled exception (type unknown) in signal handler
>
> aborting...
>
>
> this happens to me on every program i wrote that uses glib's threads

I have never thrown that exception to exit a thread and I have never looked at 
the source code to see what it does, but if glibmm relies on the underlying 
pthreads implementation not doing its own stack unwinding (which it would not 
with standard C pthreads) and therefore trying to do it itself with 
exceptions then it may well have run into a problem with the NPTL (new POSIX 
threads library) implentation of threads for Linux.  Other Unix based systems 
such as HP-UX and Solaris also have their own pthreads extension for C++ 
which may also cause problems with Glib::Thread::Exit.  I do not know whether 
Glib::Thread::Exit is compatible with Windows threads.

NPTL provides its own stack unwinding when pthreads is used in a C++ 
environment.  However, there is no standard way of doing this because C++ 
does not yet have a standard for threads.  A number of options for 
implementing thread termination in a C++ environment are:

a) Do nothing - just do nothing more than is required by POSIX pthreads, which 
is to terminate the process at the point the thread reaches a cancellation 
point (assuming deferred cancellation is used) without calling any 
destructors for local objects and to rely on the user implementing his own 
clean up handlers with pthread_cleanup_push() and pthread_cleanup_pop().  
This is what Linuxthreads users have to do (which includes FreeBSD).

b) To call the destructors on all objects with local scope ("bare stack 
unwinding") but without implementing it via a catchable exception;

c) To implement the stack unwinding as an exception.  But then, how far should 
the stack unwind - only to the point at which the thread exits or (if the 
exception is not caught) should it terminate the entire process in which the 
thread is running?  Common sense dictates the former approach (it is the only 
sane one for thread cancellation) but that would in fact contradict the C++ 
standard such as it exists at present.  But if that "non-standard" approach 
is adopted to "pseudo-exceptions" used to terminate a thread, should it also 
apply to other exceptions thrown in a multi-threaded program?  Should all 
uncaught exceptions only propagate to the point at which the thread in which 
it is thrown ends, or should it terminate all other threads executing in the 
process concerned?  There are arguments for either approach for this.

NPTL has its own slightly odd implemention for stack unwinding as an exception 
upon thread cancellation, called "forced stack unwinding", which is a 
combination of both b) and c) above.  The "pseudo-exception" involved in 
terminating a thread is anonymous but can be caught with catch(...) in order 
to do any additional clean-up the user wants to do (although catching it for 
clean-up is really relevent to calls to pthread_cancel() rather than 
pthread_exit(), as a call to pthread_exit() can be preceded by whatever 
clean-up the user wants in the ordinary course of thread execution).  
However, if that is done the catch handler MUST THEN CALL "throw" when it has 
finished its clean-up in order to carry on unwinding the stack or stack 
unwinding will proceed automatically to terminate the entire process in which 
the thread is executing (I am not sure what exception NPTL will throw to do 
this, possibly std::unexpected).  The reason given for this is that thread 
cancellation should not (in the view of the implementers of NPTL) as a matter 
of principle be capable of being stopped by catching the pseudo-exception and 
then not rethrowing it, but that does not excuse (in my view) the NPTL 
approach of terminating the entire process if the user's code does in fact 
try to do this.

Issues such as this are at present under consideration by the C++ standards 
committee for the next version of the C++ standard, which almost certainly 
will make some provision for threads, if only to deal with issues such as 
this.

The behaviour of NPTL is unintuitive (and to my mind wrong), and may trip up 
any attempt at "home grown" stack unwinding which cancels threads by throwing 
an exception at the user level (such as Glib::Thread::Exit), and then trying 
to stop stack unwinding by catching all exceptions at the point at which the 
tread terminates to enable the handler to then call pthread_exit() (or 
gthread_exit()).  With NPTL that will cause an exception to be generated in 
an exception handler with no obviously predictable result (and undefined 
behaviour).  Furthermore, if the implementation such as in glibmm causes the 
NPTL "pseudo-exception" to be caught with catch(...) and then not rethrown 
then NPTL will automatically terminate the whole process (ie, your program).

Therefore, quite probably Glib::Thread::Exit is broken with NPTL based 
distributions such as Redhat and Suse, and possibly with other Unices with 
POSIX extensions for C++.  If glibmm does what I assume it does then it has 
always been on shakey ground because of the unstandardised nature of both C++ 
exceptions in a multi-threaded program and thread termination/cancellation in 
a C++ environment.

Are you using a Unix-like operating system, and if it happens to be Linux does 
it use NPTL or Linuxthreads?

Chris.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]