This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/34152] New: Erratic behaviour: Exception translation (throw from signal handlers)


In our application we want to translate synchronous signals (such as SIGSEGV)
to C++ exceptions. 

The method is to use throw directly from either:

1 - From the signal handler itself.
2 - From a function called by the signal handler.

I'm having trouble getting this to work reliably. Test program attached below.

Building and running:

  $ g++ sigthrow.cpp -fnon-call-exceptions -fexceptions
  $ a.out
  terminate called after throwing an instance of 'char const*'
  Aborted (core dumped)
  $ 

Removing option -fnon-call-exceptions gives: 

  $ g++ sigthrow.cpp -fexceptions
  $ a.out
  ~StructWithDtor: Count 0
  Caught exception

So it works, except the frame that generated the exception is not cleaned up
(it should call a destructor for another instance of StructWithDtor).

The pattern seems to be:
1 - If the function generating the signal has objects to unwind, this is always
missed. 
2 - Also, when compiled with -fnon-call-exceptions the program often (not
always) aborts.
3 - If the function generating the signal does not have objects to unwind it
goes well (with or without -fnon-call-exceptions)


Are there some other compiler option to make this work? Something to be done in
the signal handler?

So far I haven't found any working examples of this functionality on the web.
But others have found similar difficulties. 

What is the status of this? 

It's an important feature when using plugins, script interpreters and linking
with code from other languages.

Regards
// ATS.

----------------- source -------------------------------


#include <stdio.h>
#include <csignal>
#include <unistd.h>
#include <sys/syscall.h>

typedef void(*stSignalHandlerFn)(int);

struct old_i386_kernel_sigaction {
        stSignalHandlerFn k_sa_handler;
        unsigned long k_sa_mask;
        unsigned long k_sa_flags;
        void (*sa_restorer) (void);
};

void stSigSegvHandler( int dummy ){
        void **_p = (void **)&dummy;
        struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p;
        throw "SIGSEGV signaled";
}


int g_cnt;
struct StructWithDtor { 
    StructWithDtor() : m_cnt(g_cnt++) { }
    ~StructWithDtor(){ printf("~StructWithDtor: Count %d\n", m_cnt); }
    int m_cnt;
};



int FuncNested1( int *pi ){
    StructWithDtor swd;
    return *pi;
}

int FuncTop( int *pi ){
    StructWithDtor swd;
    return FuncNested1( pi );
}

int main( int argc, const char* argv[] ) {

    // Install a SIGSEGV handler using syscall 
    struct old_i386_kernel_sigaction kact;                              
    kact.k_sa_handler = stSigSegvHandler;               
    kact.k_sa_mask = 0;                                 
    kact.k_sa_flags = 0;                                
    syscall( SYS_sigaction, SIGSEGV, &kact, NULL );

    // Trigger SIGSEGV 
    try {
        FuncTop( NULL );
    }catch( ... ){
        puts( "Caught exception\n" );
    }

}


-- 
           Summary: Erratic behaviour: Exception translation (throw from
                    signal handlers)
           Product: gcc
           Version: 4.1.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: asteinarson at gmail dot com
 GCC build triplet: Linux Ubuntu 7.10, X86-32, gcc 4.1.3 (Ubuntu default)
  GCC host triplet: Linux Ubuntu 7.10, X86-32, gcc 4.1.3 (Ubuntu default)
GCC target triplet: Linux Ubuntu 7.10, X86-32, gcc 4.1.3 (Ubuntu default)


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34152


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]