Don't understand signal - c

Could someone tell me what this line does:
if(signal(SIGUSR1, handler) == (sighandler_t)-1)
It is a line I copied from an exercise, which made it work, but I don't really understand it. Could someone explain this to me? (It is actually the second part I don't understand: what is the value of (sighandler_t)-1?)
Thank you :)
edit: the sighandler_t comes from
typedef void (*sighandler_t)(int);

First of all, it is a bad style and probably non-portable code, (sighandler_t)-1 should be replaced with one of the predefined signal dispositions. On my system they are declared in next way
/* Fake signal functions. */
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
Other systems may use another values, so assuming that your uses the same definitions, we get next code:
if(signal(SIGUSR1, handler) == SIG_ERR) {
/* got problem */
} else {
/* handler installed */
}
This code installs function handler as handler for signal SIGUSR1 and checks returned value to ensure that it was done successfully. handler must be declared as void handler(int signo);

(sighandler_t)-1 is the minus one digit, cast it into sighandler_t type. You must check to see if the signal call has failed.

Related

Why i am getting continuous SIGSEGV in the below C code

I am trying to learn Signals. I know invalid memory access will cause segfault. So, I register a signal handler for SIGSEGV signal.
#include <stdio.h>
#include <signal.h>
void sighandler(int signum)
{
printf("%s\n", __func__);
}
int main()
{
int *a = NULL;
signal(SIGSEGV, sighandler);
*a = 5;
return 0;
}
Running this code, I am continuously getting SIGSEGV Signals. I thought i should only get the signal once. Can you guys explain why I am getting signals continuously
After the SEGV handler finishes, the instruction that triggered re-executes. Since you didn't do anything to prevent the next execution from faulting, you get SEGV again, ad infinitum.
See more in this answer.
The signal handler is returning to instruction that triggered it namely *a = 5 which is causing it to loop.
You have several problems including the use of printf inside a signal handler.
There are safe and not-safe ways of dealing with this
NOTES
Using signal(2) is not recommended for signal handling in general.
Handling SIGSEGV is even more complicated because of the way the signal semantics work. Quoting from the man page:
The only portable use of signal() is to set a signal's disposition to SIG_DFL or SIG_IGN. The semantics when using signal()
to establish a signal handler vary across
systems (and POSIX.1 explicitly permits this variation); do not use it for this purpose.
POSIX.1 solved the portability mess by specifying sigaction(2), which provides explicit control of the semantics when a
signal handler is invoked; use that interface instead of signal().
So the first thing you should do is use sigaction.
Next, handling SIGSEGV is a weird beast:
How to write a signal handler to catch SIGSEGV?
and
Does linux allow any system call to be made from signal handlers?
have good answers and get into specific details. There are external links in some of the answers given there.
How to do this using signal(2)
Well :-) let's say you want to use signal(2) and you want to play with this in a weird way....
You can use sigjmpset and siglongjmp.
sigjmpset marks a point where siglongjmp should jump to. The first time sigjmpset is called (to set the point) it returns 0. When siglongjmp jumps to it, (which means it gets called again as a result of the long jump), it returns 1.
Which means we can do this:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
sigjmp_buf env;
int sigsav;
void sighandler(int signum)
{
const char msg[] = "Skipping signal\n";
write(2, msg, sizeof(msg));
siglongjmp(env, sigsav);
}
int main()
{
int *a = NULL;
signal(SIGSEGV, sighandler);
if(!sigsetjmp(env, sigsav)) {
printf("setting value of a\n");
*a = 5;
}
else {
printf("returned to sigsetjmp, but now we skip it!\n");
}
return 0;
}

Checking to see if signal arrived for given resolution

I have a server and client codes that IPC with each other via named pipes(FIFO). Client sends SIGNAL(SIGUSR1 for example) to Server and checking to see if any signal arrived with given time resolution(via command line argument). Server checks (if its 5ms) 5ms everytime, checks if any signal arrived after 5ms , if arrived it does some code , if not continues until it catches a signal.
So here is that what my problem lies. I dont know what to use for these kind of action. I looked up "Unix Systems Programming: Communication, Concurrency, and Threads Kay A. Robbins , Steven Robbins" found some functions that might be use for me. Sleep,Alarm,uSleep,NanoSleep,Pause. But i dont know which one to use in my situation. Sleep is out of question i think due it takes seconds and i think it overflows when you try to convert to milliseconds.
A little code snippet or psudocode would be nice to understand for me.
I simply asking how to check if signal arrived in given resolution frequency. I have to check if signal arrived in those milliseconds. Check any given "n" mseconds if signal catched.
I think that the function nanosleep (and also usleep) could work!
You have to install a signal handler for the desired signal that can be catched by the program, e.g.:
#include <signal.h>
/* Handler for the signals */
void my_handler(int signum)
{
if(signum == SIGUSR1) {
/* Perform an action on signal SIGUSR1*/
}
}
int main(int argc, char * argv[]){
/* .... */
/* Install the signal handler to catch the desired signals*/
signal(SIGUSR1, my_handler);
/* .... */
}
You have to loop and wait for a signal. And if you catch a signal you have to perform the actions either inside the handler or using the exception that raise when nanosleep is interrupted.
#include <time.h> /* Contains nanosleep + timespec definition */
#include <errno.h> /* Contains the errno variable and the ERROR_CODE macros */
#include <stdio.h> /* Contains definition of perror */
#include <stdlib.h> /* Contains the exit function */
int main(int argc, char * argv[]){
/* fetch milliseconds from argv and put in a variable named "ms" */
struct timespec interval;
interval.tv_sec = 0; /* Seconds*/
interval.tv_nsec = ms*1e6; /* 10^6 Nanoseconds = 1 millisecond */
struct timespec interrupted;
/* .. */
while(1) {
if(nanosleep(&interval, &interrupted) != 0){
/* The sleeping was interrupted! */
if(errno == EINTR){
//The interruption is due to a signal
}
else {
/*The interruption is due to another cause (read the man page) --> Print an error message */
perror("Nanosleep");
break; /* Exit from main loop */
}
}
return EXIT_FAILURE;
}
Alternatively you can also deal the signals inside the handlers.
Alternative Solution
If you are sure that a signal will ever come and don't need to control each 5 milliseconds you could also use the function pause. In fact the man page says:
pause causes the calling process (or thread) to sleep until a signal
is delivered that either terminates the process or causes the
invocation of a signal-catching function.
In this case you have only to install the signal handler and wait.
Let me know if it answered your question.
Sincerly yours,
Mirko

Set a custom function as handler to all signals

I have this assignment to do:
Write a function void myfunct(void(*f)(int sig)) which sets f as handler to all the possible signals.
I have two problems:
How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
Thank you.
I would personally instead iterate over a static list of signal numbers, and use preprocessor directives to detect which ones are supported (at compile time). For example:
#include <signal.h>
static const all_signals[] = {
#ifdef SIGHUP
SIGHUP, /* POSIX.1 */
#endif
#ifdef SIGQUIT
SIGQUIT, /* POSIX.1 */
#endif
#ifdef SIGTRAP
SIGTRAP, /* POSIX.1 */
#endif
#ifdef SIGIO
SIGIO, /* BSD/Linux */
#endif
/*
* Other signal names omitted for brevity
*/
/* C89/C99/C11 standard signals: */
SIGABRT,
SIGFPE,
SIGILL,
SIGINT,
SIGSEGV,
/* SIGTERM (C89/C99/C11) is also the terminating signal number */
SIGTERM
};
with SIGTERM being the last entry in the array for which a signal handler is installed:
struct sigaction act;
int i = 0;
memset(&act, 0, sizeof act);
sigemptyset(&act.sa_mask);
act.sa_handler = your_signal_handler;
act.sa_flags = 0;
do {
if (sigaction(all_signals[i], &act, NULL)) {
fprintf(stderr, "Cannot install signal %d handler: %s.\n", all_signals[i], strerror(errno));
exit(EXIT_FAILURE);
}
} while (all_signals[i++] != SIGTERM);
This way your code does not require POSIX etc. support to work, but does support POSIX signals if available at compile time.
You can check the Wikipedia Unix signal article and man 7 signal for known signal names.
You can also install the signal handler for POSIX realtime signals using
#if SIGRTMAX-0 > SIGRTMIN-0
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
if (sigaction(i, &act, NULL)) {
fprintf(stderr, "Cannot install realtime signal %d handler: %s.\n", i, strerror(errno));
exit(EXIT_FAILURE);
}
#endif
How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Most implementation provide a constant such as NSIG (Glibc provides NSIG) or _NSIG (Linux provides _NSIG). So, you can loop through that constant and set the same signal handling function for all of them.
There's no POSIX defined value for "highest signal number". There's been a proposal in POSIX to add a macro NSIG_MAX.
{NSIG_MAX}
Maximum possible return value of sysconf(_SC_NSIG). See [cross-ref to XSH sysconf()]. The value of {NSIG_MAX} shall be no greater than the number of signals that the sigset_t type (see [cross-ref to ]) is capable of representing, ignoring any restrictions imposed by sigfillset() or sigaddset().
But it hasn't made it to POSIX yet (most probably it'll a part of the POSIX version - issue 8).
Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
The parameter that the signal handling function takes doesn't matter when you are setting a signal disposition. It takes the signal number but that doesn't prevent you from using it as a handler for multiple signals.
But there are special cases you need to handle. Certain signals that can't caught or ignored (SIGKILL and SIGSTOP). There are other signals (SIGFPE, SIGILL and SIGSEGV) for which, while allowed to caught, the signal handler can't return to its caller (i.e. you need exit from the signal handler).
1. How can a get all the possible signals? Is there a function for this? Can I iterate through them in some way?
Seems like there isn't a standardized list you can iterate, but we actually don't need such a list for your task. Signal numbers are always positive and at most SIGRTMAX. In between 1 and SIGRTMAX there might be some numbers that do not correspond to any signal, but you can still try to set a handler for these. From the posix specification of sigaction(sig, ...) (emphasis mine):
RETURN VALUE
Upon successful completion, sigaction() shall return 0; otherwise, -1 shall be returned, errno shall be set to indicate the error, and no new signal-catching function shall be installed.
ERRORS
The sigaction() function shall fail if:
[EINVAL]
The sig argument is not a valid signal number or an attempt is made to catch a signal that cannot be caught or ignore a signal that cannot be ignored.
So it is perfectly fine to call sigaction(123, ...) where 123 is not a signal.
2. Will it really work to set the function f as handler given that it takes a parameter? Shouldn't it not have any parameters?
Why do you think it should have no parameters?
Again, from the posix specification of sigaction():
Member Type
Member Name
Description
void(*) (int)
sa_handler
Pointer to a signal-catching function
The signal handler is supposed to have an int parameter, just like your function f has, so there is no problem.
Putting everything together
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
struct sigaction siga;
void f(int sig) {
printf("Caught signal %d\n", sig);
}
// sets f as handler to all the possible signals.
void myfunct(void(*f)(int sig)) {
siga.sa_handler = f;
for (int sig = 1; sig <= SIGRTMAX; ++sig) {
// this might return -1 and set errno, but we don't care
sigaction(sig, &siga, NULL);
}
}
int main() {
myfunct(f);
pause(); // wait for signal
return 0;
}

Can a C program continue execution after a signal is handled?

I'm new at signal handling in Unix through C and I have been looking at some tutorials on it (out of pure interest).
My questions is, is it possible to continue execution of a program past the point where a signal is handled?
I understand that the signal handling function does the cleanup but in the spirit of exception handling (such as in C++), is it possible for that signal to be handled in the same fashion and for the program to continue running normally?
At the moment catch goes in an infinite loop (presumably a way to quit would be to call exit(1) ).
My intention would be for b to be assigned 1 and for the program to finish gracefully (if that is possible of course).
Here's my code:
#include <signal.h>
#include <stdio.h>
int a = 5;
int b = 0;
void catch(int sig)
{
printf("Caught the signal, will handle it now\n");
b = 1;
}
int main(void)
{
signal(SIGFPE, catch);
int c = a / b;
return 0;
}
Also, as C is procedural, how come the signal handler declared before the offending statement is actually called after the latter has executed?
And finally, in order for the handling function to do its clean up properly, all the variables than need to be cleaned up in the event of an exception need to be declared prior to the function, right?
Thanks in advance for your answers and apologies if some of the above is very obvious.
Yes, that's what signal handlers are for. But some signals need to be handled specially in order to allow the program to continue (e.g. SIGSEGV, SIGFPE, …).
See the manpage of sigaction:
According to POSIX, the behavior of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not
generated by kill(2) or raise(3). Integer division by zero has undefined result. On some architectures it will generate a
SIGFPE signal. (Also dividing the most negative integer by -1 may generate SIGFPE.) Ignoring this signal might lead to an
endless loop.
Right now, you are ignoring the signal, by not doing anything to prevent it from happening (again). You need the execution context in the signal handler and fix it up manually, which involves overwriting some registers.
If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of
sa_handler) specifies the signal-handling function for signum. This
function receives the signal number as its first argument, a pointer
to a siginfo_t as its second argument and a pointer to a ucontext_t
(cast to void *) as its third argument. (Commonly, the handler
function doesn't make any use of the third argument. See
getcontext(2) for further information about ucontext_t.)
The context allows access to the registers at the time of fault and needs to be changed to allow your program to continue. See this lkml post. As mentioned there, siglongjmp might also be an option. The post also offers a rather reusable solution for handling the error, without having to make variables global etc.:
And because you handle it youself, you have any flexibility you want
to with error handling. For example, you can make the fault handler
jump to some specified point in your function with something like
this:
__label__ error_handler;
__asm__("divl %2"
:"=a" (low), "=d" (high)
:"g" (divisor), "c" (&&error_handler))
... do normal cases ...
error_handler:
... check against zero division or overflow, so whatever you want to ..
Then, your handler for SIGFPE needs only to do something like
context.eip = context.ecx;
If you know what you are doing, you can set the instruction pointer to point right after the offending instruction. Below is my example for x86 (32bit and 64bit). Don't try at home or in real products !!!
#define _GNU_SOURCE /* Bring REG_XXX names from /usr/include/sys/ucontext.h */
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ucontext.h>
static void sigaction_segv(int signal, siginfo_t *si, void *arg)
{
ucontext_t *ctx = (ucontext_t *)arg;
/* We are on linux x86, the returning IP is stored in RIP (64bit) or EIP (32bit).
In this example, the length of the offending instruction is 6 bytes.
So we skip the offender ! */
#if __WORDSIZE == 64
printf("Caught SIGSEGV, addr %p, RIP 0x%lx\n", si->si_addr, ctx->uc_mcontext.gregs[REG_RIP]);
ctx->uc_mcontext.gregs[REG_RIP] += 6;
#else
printf("Caught SIGSEGV, addr %p, EIP 0x%x\n", si->si_addr, ctx->uc_mcontext.gregs[REG_EIP]);
ctx->uc_mcontext.gregs[REG_EIP] += 6;
#endif
}
int main(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = sigaction_segv;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
/* Generate a seg fault */
*(int *)NULL = 0;
printf("Back to normal execution.\n");
return 0;
}
In general, yes, execution continues after the handler returns. But if the signal was caused by a hardware error (such as a floating point exception or a segmentation fault), you have no way of undoing that error, and so your program will be terminated regardless.
In other words, you have to distinguish between signals and things that cause signals. Signals by themselves are perfectly fine and handlable, but they don't always let you fix errors that cause signals.
(Some signals are special, such as ABRT and STOP, in the sense that even if you just raise such a signal manually with kill, you still can't "prevent its effects". And of course KILL cannot even be handled at all.)

SIGSEGV recovery?

I ve got some SSE procedure which zeroes memory in loop,
When pointer is unaligned it raises SIGSEGV which goes
into my handler. Can I get more info here in such handler
routine, Now I got no info where it was done, can I also
react in some predictible way from it? When I chose to
ignore it It seemd to me that it should go back and becouse
it was in loop raise SIGSEGV again, (got such behaviour with
division by zero when where I ignore it it just goes on
further) but it does not work here such way but sadly just
crashes after ignoring. Can I do some more eleborate recovery here?
EDIT - ADD
in my signal.h (some very old win32 compiler but I use it)
I have such stuff
/* _SIGCONTEXT contains exception info for WIN32 exceptions that were caught
and turned into signals. There will always be three 32-bit parameters
passed to the user's signal handler. Unused parameters will be 0. The
_PSIGCONTEXT parameter will always be the last (third) parameter.
*/
typedef struct
{
struct _EXCEPTION_RECORD * _pexecptionrecord; /* defined in WINNT.H */
struct _CONTEXT * _pcontext; /* defined in WINNT.H */
unsigned long _result; /* return value for the SEH */
} _SIGCONTEXT, *_PSIGCONTEXT;
typedef int sig_atomic_t; /* Atomic entity type (ANSI) */
typedef void (*_CatcherPTR)(int);
#define SIG_DFL ((_CatcherPTR)0) /* Default action */
#define SIG_IGN ((_CatcherPTR)1) /* Ignore action */
#define SIG_ERR ((_CatcherPTR)-1) /* Error return */
//////////////////////////////////
//skipped #define SIGABRT 22
// #define SIGFPE 8 .... constants block here
int raise(int __sig);
void (*signal(int __sig, void (*__func)(int) )) (int);
Signal Raise are understood for me but how to get to data of SIGCONTEXT or use 'catcher' ?
While it is possible on some operating systems under certain circumstances to catch and handle SIGSEGV, SIGBUS, SIGILL and SIGFPE it's a really bad idea to do anything other than crashing. They indicate a bug in your program that you need to fix, not something you just sweep under the rug.
But in case you really enjoy shooting yourself in the foot and leaving horrible undebuggable and unmaintainable messes that others will have to clean up after you while cursing you and your ancestors while wishing that voodoo worked, have a peek at the documentation for sigaction() and how siginfo_t. They contain at least some parts of what you need.

Resources