Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Sep 1998 18:13:47 +0000 (GMT)
From:      Terry Lambert <tlambert@primenet.com>
To:        smp@csn.net (Steve Passe)
Cc:        tlambert@primenet.com, joelh@gnu.org, obrien@NUXI.com, dfr@nlsystems.com, jb@cimlogic.com.au, current@FreeBSD.ORG
Subject:   Re: Compiler problems with gcc-2.7.2.1
Message-ID:  <199809101813.LAA26539@usr08.primenet.com>
In-Reply-To: <199809101556.JAA05124@Ilsa.StevesCafe.com> from "Steve Passe" at Sep 10, 98 09:56:29 am

next in thread | previous in thread | raw e-mail | index | archive | help
> We found that these patches only fix half the problem with 2.8.1.  Note
> this piece of code in libgcc2.c:
> 
>   /* We must call terminate if we try and rethrow an exception, when
>      there is no exception currently active and when there are no
>      handlers left.  */
>   if (! __eh_info || (*dhc) == top_elt)
>                                ^^^^^^^
>     __terminate ();
> 
> The original patches correctly create a per-thread dynamic_handler_chain,
> but the code in __sjthrow () walks off the end of the world when unwinding
> the chain in a throw() attempt.  This usually creates the classical 
> threads prog hang with the program consumming 99% of the CPU and going
> nowhere, othertimes you get a segfault of other coredump.

I haven't seen this.

Did you enable the code in uthread_init.c and rebuild libc_r before
trying this?


> The specific problem is that top_elt (the original global "top of dhc")
> is not in the chain with the per-thread dhc scheme, and thus never matched.


It is, if you enabled the code in uthread_init.c:

=============================================================================
typedef void *** (*dynamic_handler_allocator)();
extern void __set_dynamic_handler_allocator(dynamic_handler_allocator);

static pthread_key_t except_head_key;

typedef struct {
  void **__dynamic_handler_chain;
  void *top_elt[2];
} except_struct;

static void ***dynamic_allocator_handler_fn()
{
        except_struct *dh = (except_struct *)pthread_getspecific(except_head_key
);

        if(dh == NULL) {
                dh = (except_struct *)malloc( sizeof(except_struct) );
                memset(dh, '\0', sizeof(except_struct));
                dh->__dynamic_handler_chain= dh->top_elt;
                pthread_setspecific(except_head_key, (void *)dh);
        }
        return &dh->__dynamic_handler_chain;
}
=============================================================================
**** Fourth line up! *************************************************


And immediately before the final return in _thread_init():

=============================================================================
        /* Create the thread-specific data for the exception linked list. */
        if(pthread_key_create(&except_head_key, NULL) != 0)
                PANIC("Failed to create thread specific execption head");
                        
        /* Setup the gcc exception handler per thread. */
        __set_dynamic_handler_allocator( dynamic_allocator_handler_fn );
=============================================================================


> This is fixed in the attached updated patch.  Note  that it is a QUICK hack
> with little thought to "beauty",  I needed to fry more important fish at
> the time.  More importantly, it doesn't completely fix the problem.  The
> part where you walk off into the weeds is gone, it properly walks back up
> the stack, running all the destructors.  But it doesn't seem to get back
> to thecatch() statement.  Instead it hits the __terminate() statement,
> ignoring the catch() block.  I havn't had time to figure out why,
> if anyone does, please post!


Subclassing classes of exceptions appears to fail, if done directly;
at least, it has been my experience that attempting to recover RTTI
from "throw classname()" style immediate copy-construction fails.

What I normally do is something like (this is from my Exception.H from
my implementation of the JAVA classes in C++):

=============================================================================
class Exception {
public:
        Exception( void) { };
        virtual ~Exception( void) { };
};

Exception
#ifdef _EXCEPTION_CC
#define _EXCEPTION(x,y) class _ ## x : public y {                       \
                                        public:                         \
                                            _ ## x( void) { };          \
                                            virtual ~_ ## x( void) { }; \
                                        };                              \
                        Exception       *x = (Exception *)new _ ## x ();
#define EXCEPTION(x,y)  _EXCEPTION(x, _ ## y)
#else   // !EXCEPTION_CC
#define _EXCEPTION(x,y) class _ ## x : public y {                       \
                                        public:                         \
                                            _ ## x( void) { };          \
                                            virtual ~_ ## x( void) { }; \
                                        };                              \
                        extern Exception        *x;
#define EXCEPTION(x,y)  _EXCEPTION(x, _ ## y)
#endif  // !EXCEPTION_CC

_EXCEPTION(RuntimeException, Exception)

  EXCEPTION(ArithmeticException, RuntimeException)
  EXCEPTION(ArrayStoreException, RuntimeException)

...
=============================================================================


Then in Exception.cc:

=============================================================================
#define _EXCEPTION_CC   1

#include <java/lang/Exception.H>
=============================================================================


Then to throw (this is from the javax/mail API implementation in C++):

=============================================================================
	throw MessagingException;
=============================================================================


And to attempt/catch (this is from javax/mail/MessageClass):

=============================================================================
bool
Message::isSet( Flag flag)
{   
    Flags       *flags;
    bool        rv = false;
    
    try {
        flags = getFlags();
        rv = flags->contains( flag);
        delete flags; 
    }
    catch( Exception *ep) {
        delete flags; 
        throw ep;               // rethrow exception
    }
 
    return( rv);
}
=============================================================================


This was necessary to make the RTTI return the correct information
on a class pointer that was a subclass of the Exception class.

Basically, you have instanced an Exception * pointer to each
instance of subclass, and then thrown these pointers instead
of constructing them at runtime.


What you should really try is to catch *everything* and see if what
you are seeing is a failure to catch, or a catch target type
mismatch.


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809101813.LAA26539>