Loading...
You are not logged-in Login/Register





  • Posts   Search Threads
  • michael.marronel-3com.comJune 23, 2009 12:43 PM PDT   
    Signal Handler on a Linux system.

    We are moving our software baseline from a Unix operating system to a Linux operating system.  I am trying to change our unix signal handler to use the linux based signal routines.  I have to trap the following signals:  SIGFPE, SIGILL, SIGSEGV, and SIGTRAP.  The signal handler works using the following simple routine #1 layout, but I cannot get and print the stack frame as it is when the signal/exception occurs.  It gives me the stack frame as it is after the signal has been trapped.  I then researched on the internet, and found out that this is a problem that a lot of people have, and their fix was to use the routine #2 layout.  I cannot get routine #2 to compile using the icc compiler.  I have tried a lot of different #define options, but that just generates a different set of compiler errors.  If anyone has ever done this before, could you please show me the code that works using the icc compiler.

    Routine #1 layout:

    #define _POSIX_SOURCE 199309

    #include <stdio.h>

    #include <stdlib.h>

    #include <signal.h>

    #include <execinfo.h>

    #include <setjmp.h>

     

    void MyStackWalker (void)

    {

                void     *trace[10];

                int        i;

                int        trace_size = 0

                char    **messages = (char**)NULL;

     

     

                trace_size = backtrace(trace, 10);

                messages = backtrace_symbols(trace, trace_size);

     

                for (i=0; i<trace_size; i++)

                {

                            printf("n[bt]  %s", messages[i]);

                }

     

                free (messages);

    }

     

    void MySignalHandler (int signo)

    {

                If (signo == SIGFPE)

                {

                            printf("n A floating point exception has been detected.");

                            MyStackWalker();

                }

                else if (signo == SIGSEGV)

                {

                            printf("n A segmentation violation has been detected.");

                            MyStackWalker();

     

                }

                else if (signo == SIGILL)

                {

                            printf("n An illegal operation has been detected.");

                            MyStackWalker();

     

                }

                else if (signo == SIGTRAP)

                {

                            printf("n A out of bounds array has been detected.");

                            MyStackWalker();

     

                }

                else

                {

                            printf("n An unknown exception has been detected.");

                            MyStackWalker();

     

                }

    }

     

     

    Int main()

    {

                struct sigaction newAct;

                struct sigaction oldAct;

     

                newAct.sa_handler = MySignalHandler;

                sigemptyset (&newAct.sa_mask);

                newAct.sa_flags = 0:

     

     

                sigaction(SIGFPE, NULL, &oldAct);

                if (oldAct.sa_handler != SIG_IGN)

    {

                            sigaction(SIGFPE, &newAct, NULL);

    }

               

    sigaction(SIGILL, NULL, &oldAct);

    if (oldAct.sa_handler != SIG_IGN)

    {

                            sigaction(SIGILL, &newAct, NULL);

    }          

               

                sigaction(SIGSEGV NULL, &oldAct);

    if (oldAct.sa_handler != SIG_IGN)

    {

                            sigaction(SIGSEGV, &newAct, NULL);

    }

               

                sigaction(SIGTRAP, NULL, &oldAct);

    if (oldAct.sa_handler != SIG_IGN)

    {

                            sigaction(SIGTRAP, &newAct, NULL);

    }

               

    }

     

    Routine #2 layout

    #define _POSIX_SOURCE 199309

    #include <stdio.h>

    #include <stdlib.h>

    #include <signal.h>

    #include <execinfo.h>

    #include <setjmp.h>

    #include <unistd.h>

     

    #define __USE_GNU

    #include <sys/ucontext.h>

     

    void MyStackWalker (siginfo_t *info, void *my_eip)

    {

                void     *trace[10];

                int        i;

                int        trace_size = 0

                char    **messages = (char**)NULL;

     

     

                trace_size = backtrace(trace, 10);

                trace[1] = (void*)ux->uc_mcontext.gregs[REG_EIP];

                messages = backtrace_symbols(trace, trace_size);

     

                ucontext_t *uc = (ucontext_t *)my_eip;

     

                for (i=0; i<trace_size; i++)

                {

                            printf("n[bt]  %s", messages[i]);

                }

     

                free (messages);

    }

     

    void MySignalHandler (int signo, siginfo_t *into, void *my_eip)

    {

                If (signo == SIGFPE)

                {

                            printf("n A floating point exception has been detected.");

                            MyStackWalker(info, my_eip);

                }

                else if (signo == SIGSEGV)

                {

                            printf("n A segmentation violation has been detected.");

                            MyStackWalker(info, my_eip);

     

                }

                else if (signo == SIGILL)

                {

                            printf("n An illegal operation has been detected.");

                            MyStackWalker(info, my_eip);

     

                }

                else if (signo == SIGTRAP)

                {

                            printf("n A out of bounds array has been detected.");

                            MyStackWalker(info, my_eip);

     

                }

                else

                {

                            printf("n An unknown exception has been detected.");

                            MyStackWalker(info, my_eip);

     

                }

    }

     

     

    Int main()

    {

                struct sigaction newAct;

     

                newAct.sa_sigaction= &MySignalHandler;

                sigemptyset (&newAct.sa_mask);

                newAct.sa_flags = SA_RESTART | SA_SIGINFO:

               

                sigaction(SIGFPE, &newAct, NULL);

                sigaction(SIGILL, &newAct, NULL);

                sigaction(SIGSEGV, &newAct, NULL);

                sigaction(SIGTRAP, &newAct, NULL);

               

    }

     




    Om Sachan (Intel)June 23, 2009 11:39 PM PDT
    Rate
     
    Re: Signal Handler on a Linux system.


    I could not compile the secod case even with gcc. Could you please help with compilable test case with gcc and command line.  

    michael.marronel-3com.comJune 24, 2009 8:11 AM PDT
    Rate
     
    Re: Signal Handler on a Linux system.


    I could not compile the secod case even with gcc. Could you please help with compilable test case with gcc and command line.  

    That is what my problem is, the structure with sa_sigaction exists in the sigaction.h include file, it also does incorporate the 3 return arguments (instead of just signo), but I cannot get it to compile on our system.  This solution was one I found on the internet after searching for signal handlers on Linux systems.  I tried a plethera of different #define flags to see if I could force it to use the correct version of the sigaction structure with the added arguments, but to no avail.  I cannot get this to work on the Linux system using gcc or icc.  Is there another way to do it using icc?  I have to be able to capture the signal, print the call stack, and re-display the Motif window notifying the operator that a signal was caught so that they can gracefully exit the process and notify a analyst to take a look at it.  The call stack printing is to assist the analyst with what the process was doing when it received a signal.  Everything works with the first solution, except that it prints the "new" call stack containing just the signal handler information.  The only solution I can find to get to the previous stack frame "old" call stack, was the routine #2 solution.  According to the include files on the system, the system should support the second solution, I just can't figure out what I am missing to get it to compile.

    Feilong H. (Intel)July 2, 2009 2:30 AM PDT
    Rate
     
    Re: Signal Handler on a Linux system.


    Mark, one of my colleagues, fixed syntax error in your code. That makes the code works on IA-32.


    ================== t2.cpp for IA32 ================
    #define _POSIX_SOURCE 199309

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <execinfo.h>
    #include <setjmp.h>
    #include <unistd.h>

    #define __USE_GNU 1
    #include <sys/ucontext.h>



    void MyStackWalker (siginfo_t *info, void *my_eip)
    {
    void *trace[10];
    int i;
    int trace_size = 0;
    char **messages = (char**)NULL;
    trace_size = backtrace(trace, 10);
    messages = backtrace_symbols(trace, trace_size);
    ucontext_t *uc = (ucontext_t *)my_eip;
    trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
    for (i=0; i<trace_size; i++)
    {
    printf("n[bt] %s", messages[i]);
    }
    free (messages);
    }
    void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
    {
    if (signo == SIGFPE)
    {
    printf("n A floating point exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGSEGV)
    {
    printf("n A segmentation violation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGILL)
    {
    printf("n An illegal operation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGTRAP)
    {
    printf("n A out of bounds array has been detected.");
    MyStackWalker(info, my_eip);
    }
    else
    {
    printf("n An unknown exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    }
    int main()
    {
    struct sigaction newAct;
    newAct.sa_sigaction= &MySignalHandler;
    sigemptyset (&newAct.sa_mask);
    newAct.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction(SIGFPE, &newAct, NULL);
    sigaction(SIGILL, &newAct, NULL);
    sigaction(SIGSEGV, &newAct, NULL);
    sigaction(SIGTRAP, &newAct, NULL);
    }
    ============================================

    $ icc -V
    Intel(R) C Compiler Professional for applications running on IA-32, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
    Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

    $ icpc t2.cpp
    $ g++ t2.cpp
    $


    However, above code doesn't compile on Intel 64.  Then I did some further investigation.It looks that REG_EIP only works on IA-32. In /usr/include/sys/ucontext.h, you may see something like this


    #if __WORDSIZE == 64
    ...
    enum
    {
    REG_R8 = 0,
    # define REG_R8 REG_R8
    REG_R9,
    # define REG_R9 REG_R9
    REG_R10,
    # define REG_R10 REG_R10
    REG_R11,
    ...
    REG_RIP,
    # define REG_RIP REG_RIP
    ...
    };

    #else /* __WORDSIZE == 32 */

    enum
    {
    ...
    REG_EIP,
    # define REG_EIP REG_EIP
    REG_CS,
    # define REG_CS REG_CS
    REG_EFL,
    # define REG_EFL REG_EFL
    REG_UESP,
    # define REG_UESP REG_UESP
    REG_SS
    # define REG_SS REG_SS
    };
    #endif


    So, on IA-32, REG_EIP is an enum value. But on Intel 64, REG_EIP is not defined.  It seems that you should use REG_RIP instead on Intel 64.  With this modification, t2.cpp compiles.  See below.


    =========== t2.cpp for Intel 64 ================
    #define _POSIX_SOURCE 199309

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <execinfo.h>
    #include <setjmp.h>
    #include <unistd.h>

    #define __USE_GNU 1
    #include <sys/ucontext.h>



    void MyStackWalker (siginfo_t *info, void *my_eip)
    {
    void *trace[10];
    int i;
    int trace_size = 0;
    char **messages = (char**)NULL;
    trace_size = backtrace(trace, 10);
    messages = backtrace_symbols(trace, trace_size);
    ucontext_t *uc = (ucontext_t *)my_eip;
    trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
    for (i=0; i<trace_size; i++)
    {
    printf("n[bt] %s", messages[i]);
    }
    free (messages);
    }
    void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
    {
    if (signo == SIGFPE)
    {
    printf("n A floating point exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGSEGV)
    {
    printf("n A segmentation violation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGILL)
    {
    printf("n An illegal operation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGTRAP)
    {
    printf("n A out of bounds array has been detected.");
    MyStackWalker(info, my_eip);
    }
    else
    {
    printf("n An unknown exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    }
    int main()
    {
    struct sigaction newAct;
    newAct.sa_sigaction= &MySignalHandler;
    sigemptyset (&newAct.sa_mask);
    newAct.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction(SIGFPE, &newAct, NULL);
    sigaction(SIGILL, &newAct, NULL);
    sigaction(SIGSEGV, &newAct, NULL);
    sigaction(SIGTRAP, &newAct, NULL);
    }
    =======================================

    $ icc -V
    Intel(R) C Intel(R) 64 Compiler Professional for applications running on Intel(R) 64, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
    Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

    $ icpc t2.cpp
    $ g++ t2.cpp
    $


    michael.marronel-3com.comJuly 7, 2009 9:11 AM PDT
    Rate
     
    Re: Signal Handler on a Linux system.


    Mark, one of my colleagues, fixed syntax error in your code. That makes the code works on IA-32.


    ================== t2.cpp for IA32 ================
    #define _POSIX_SOURCE 199309

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <execinfo.h>
    #include <setjmp.h>
    #include <unistd.h>

    #define __USE_GNU 1
    #include <sys/ucontext.h>



    void MyStackWalker (siginfo_t *info, void *my_eip)
    {
    void *trace[10];
    int i;
    int trace_size = 0;
    char **messages = (char**)NULL;
    trace_size = backtrace(trace, 10);
    messages = backtrace_symbols(trace, trace_size);
    ucontext_t *uc = (ucontext_t *)my_eip;
    trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
    for (i=0; i<trace_size; i++)
    {
    printf("n[bt] %s", messages[i]);
    }
    free (messages);
    }
    void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
    {
    if (signo == SIGFPE)
    {
    printf("n A floating point exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGSEGV)
    {
    printf("n A segmentation violation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGILL)
    {
    printf("n An illegal operation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGTRAP)
    {
    printf("n A out of bounds array has been detected.");
    MyStackWalker(info, my_eip);
    }
    else
    {
    printf("n An unknown exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    }
    int main()
    {
    struct sigaction newAct;
    newAct.sa_sigaction= &MySignalHandler;
    sigemptyset (&newAct.sa_mask);
    newAct.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction(SIGFPE, &newAct, NULL);
    sigaction(SIGILL, &newAct, NULL);
    sigaction(SIGSEGV, &newAct, NULL);
    sigaction(SIGTRAP, &newAct, NULL);
    }
    ============================================

    $ icc -V
    Intel(R) C Compiler Professional for applications running on IA-32, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
    Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

    $ icpc t2.cpp
    $ g++ t2.cpp
    $


    However, above code doesn't compile on Intel 64.  Then I did some further investigation.It looks that REG_EIP only works on IA-32. In /usr/include/sys/ucontext.h, you may see something like this


    #if __WORDSIZE == 64
    ...
    enum
    {
    REG_R8 = 0,
    # define REG_R8 REG_R8
    REG_R9,
    # define REG_R9 REG_R9
    REG_R10,
    # define REG_R10 REG_R10
    REG_R11,
    ...
    REG_RIP,
    # define REG_RIP REG_RIP
    ...
    };

    #else /* __WORDSIZE == 32 */

    enum
    {
    ...
    REG_EIP,
    # define REG_EIP REG_EIP
    REG_CS,
    # define REG_CS REG_CS
    REG_EFL,
    # define REG_EFL REG_EFL
    REG_UESP,
    # define REG_UESP REG_UESP
    REG_SS
    # define REG_SS REG_SS
    };
    #endif


    So, on IA-32, REG_EIP is an enum value. But on Intel 64, REG_EIP is not defined.  It seems that you should use REG_RIP instead on Intel 64.  With this modification, t2.cpp compiles.  See below.


    =========== t2.cpp for Intel 64 ================
    #define _POSIX_SOURCE 199309

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <execinfo.h>
    #include <setjmp.h>
    #include <unistd.h>

    #define __USE_GNU 1
    #include <sys/ucontext.h>



    void MyStackWalker (siginfo_t *info, void *my_eip)
    {
    void *trace[10];
    int i;
    int trace_size = 0;
    char **messages = (char**)NULL;
    trace_size = backtrace(trace, 10);
    messages = backtrace_symbols(trace, trace_size);
    ucontext_t *uc = (ucontext_t *)my_eip;
    trace[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
    for (i=0; i<trace_size; i++)
    {
    printf("n[bt] %s", messages[i]);
    }
    free (messages);
    }
    void MySignalHandler (int signo, siginfo_t *info, void *my_eip)
    {
    if (signo == SIGFPE)
    {
    printf("n A floating point exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGSEGV)
    {
    printf("n A segmentation violation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGILL)
    {
    printf("n An illegal operation has been detected.");
    MyStackWalker(info, my_eip);
    }
    else if (signo == SIGTRAP)
    {
    printf("n A out of bounds array has been detected.");
    MyStackWalker(info, my_eip);
    }
    else
    {
    printf("n An unknown exception has been detected.");
    MyStackWalker(info, my_eip);
    }
    }
    int main()
    {
    struct sigaction newAct;
    newAct.sa_sigaction= &MySignalHandler;
    sigemptyset (&newAct.sa_mask);
    newAct.sa_flags = SA_RESTART | SA_SIGINFO;
    sigaction(SIGFPE, &newAct, NULL);
    sigaction(SIGILL, &newAct, NULL);
    sigaction(SIGSEGV, &newAct, NULL);
    sigaction(SIGTRAP, &newAct, NULL);
    }
    =======================================

    $ icc -V
    Intel(R) C Intel(R) 64 Compiler Professional for applications running on Intel(R) 64, Version 11.0 Build 20090609 Package ID: l_cproc_p_11.0.084
    Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

    $ icpc t2.cpp
    $ g++ t2.cpp
    $


    Thanks,  I just returned to work from vacation, and will try this fix This week.  I will let you know if it works on our system.


Forum jump:  

Intel Software Network Forums Statistics

16,371 users have contributed to 46,346 threads and 163,988 posts to date.

In the past 24 hours, we have 15 new thread(s) 83 new posts(s), and 61 new user(s).

In the past 3 days, the most popular thread for everyone has been Formula for the intersection of straight lines The most posts were made to Take a look at John Burkhard&# The post with the most views is \"-check none\" generates error

Please welcome our newest member claudepi


For more complete information about compiler optimizations, see our Optimization Notice.