Forum Jump

Select Group :
Select Forum :
Sorted By :
Sort Order :
From The :
 
Thread Tools  Search this thread 
michael.marronel-3com.com
Total Points:
50
Status Points:
0
Green Belt
June 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)
Total Points:
7,270
Status Points:
6,770
Brown Belt
June 23, 2009 11:39 PM PDT
Rate
 
#1

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.com
Total Points:
50
Status Points:
0
Green Belt
June 24, 2009 8:11 AM PDT
Rate
 
#2 Reply to #1

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)
Total Points:
1,697
Status Points:
1,197
Brown Belt
July 2, 2009 2:30 AM PDT
Rate
 
#3

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.com
Total Points:
50
Status Points:
0
Green Belt
July 7, 2009 9:11 AM PDT
Rate
 
#4 Reply to #3

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.




Intel Software Network Forums Statistics

8491 users have contributed to 31629 threads and 100769 posts to date.
In the past 24 hours, we have 28 new thread(s) 129 new posts(s), and 184 new user(s).

In the past 3 days, the most popular thread for everyone has been Implicite multithreading ??? The most posts were made to Crash when loading skeleton The post with the most views is Dear Steve, excuse me for a d

Please welcome our newest member shadowwolf99