[295] in Pthreads mailing list archive

home help back first fref pref prev next nref lref last post

Re: pthread_cancel() and c++ destructors

daemon@ATHENA.MIT.EDU (David Brownell)
Sat Mar 16 18:08:21 1996

Date: Sat, 16 Mar 1996 10:18:38 -1000
From: David Brownell <brownell@ix.netcom.com>
To: Ken Raeburn <raeburn@cygnus.com>
Cc: pthreads@MIT.EDU

Ken Raeburn wrote:
> 
>    From: David Brownell <brownell@ix.netcom.com>
> 
>    The only implementation of MT/C++ that I _know_ has paid attention to
>    integrating the two properly is on Solaris 2.5, and that's what it does.
>    Last I checked (a year ago) nobody had done that for G++ and a pthreads
>    implementation such as MIT's.  (But folk were quite open to modifying
>    both appropriately.)
> 
> It would be nice if the g++ exception mechanism were thread-safe.  I
> complained to mrs about this, oh, probably at least 6 months ago.  It
> uses global variables.  It would also be nice if it worked on all
> systems, with optimization.  Far as I'm concerned, the g++ eh code
> just doesn't work until these are fixed.

Sounds fair -- I knew there were optimization problems back then; if I
were using my G++/Linux box more, I'd know this hadn't changed.  How
tough will it be to fix the optimizer bugs?  I may not want to know!

Re global variables, lacking kernel support for threads sharing the same
address space, I suspect it could "work" to use global variables if you
did the signal handling correctly.  The "good" way to do exceptions is
zero-overhead except when they're thrown:  tables of exception data that
get parsed during stack unwinding for exceptions (or cancellation).  The
tables are read-only, so don't cause MT problems.  I'd thought that was
what MRS intended; perhaps that's not what the code does now.


>    The options are basically to use the existing C++ stack unwind-protect
>    mechanism, or invent a new one like POSIX did in its C binding (POSIX.1c
>    defined pthread_cleanup_push/pop).
> 
>    That's an easy choice for a developer, since the latter means that the
>    built-in C++ mechanism can't _ever_ be used.
> 
> Why not? 

I guess I have a black-and-white mindset there:  if you have two
mechanisms to do something, and one doesn't work, use the other.

(Keep in mind I said "OR" ... I see no reason to have two mechanisms
to do the same thing here, since IMHO C++ destructors are a natural
and clean way to package this functionality in C++.)

> 	It may not be portable to rely on, but I think any vendor
> shipping quality implementations of pthreads and C++ will make sure
> they play nice together. 

Yes, I hope any vendor shipping quality implementations of threads
and C++ will make sure they work together.  But it takes time, and
some kind of consensus about what to do ... and experience implementing
the stuff too.  We seem to be working on those issues!

I'll note that the Visual C++ environment doesn't (so far as I know)
clean up during the Win32 equivalent of pthread_cancel ... so this area
of "stopping threads before their time" is not the most robust in any of
the currently viable threading environments.  (It's even new-ish code in
Solaris 2.5, and we all know what "new code" means.)

>	 Just put the EH hooks into the C compiler,
> build pthread_cleanup_* on top, and make pthread_cancel raise a magic
> exception in the context of the cancelled thread.

That was what MRS and I had talked about, though there were some issues
associated with the "raise the exception".  A few points that come to
mind right away:

	- pthread_cleanup_* can also be done with macros and TSD, per
	  the POSIX spec.  Not pretty or fast, but doable. (And not the
	  kind of stuff I'd want to build into a binary interface that
	  musn't ever change!)

	- If pthread_cancel uses the C++ exception cleanup code, then 
	  some interface is needed between the pthread runtime and the
	  C++ runtime -- private glue, not for portable code to use.

	- If an "exception" were thrown, C++ code could catch it and then
	  continue running.  But POSIX stipulates that cancellation means
	  the thread should go away.  And C++ stipulates that lots of code
	  would need to be modified to declare "throw (..., xcancel)" else
	  cancellation would cause unexpected() to be called.  So, I think
	  that throwing an exception is probably not the best answer, and
	  the that "glue" would not check "catch" clauses at all.  (The
	  POSIX cancellation is "like" exceptions and reuses most of the
	  exception processing machinery ... but it's not C++ exceptions.)

	- Oh yes, why do I like compiler support for pthread_cleanup.
	  Imagine a stack that has alternating frames of C/C++ code,
	  each grabbing locks in the correct order.  You need to call each
	  stack frame's "cleanup" code (C "cleanup functions", and for
	  C++ the destructors) in the right order ... the "glue" needs
	  to have a deal with several parties, and I don't know of a good
	  way not to have the compiler be one of those parties.

I suppose it's discussions like this that make folk conclude that threads
really ought to be part of the programming language, so that there aren't
such fuzzy lines between the language's runtime environment and support that
the OS provides to it.
-- 
David Brownell <brownell@ix.netcom.com>

home help back first fref pref prev next nref lref last post