Reputation: 810
Signal takes a callback function as one of its arguments. To have variable behaviour I want to create a function within a function. This is my attempt so far:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler
}
int main(void) {
...
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
...
}
...
}
But, every time I send a SIGTSTP (Ctrl-z), I get a seg fault.
As a sidenote: any tips on how to debug seg faults in general would be really appreciated!
Upvotes: 2
Views: 524
Reputation: 6777
Your code compiles because it's syntactically correct and you're using compiler extensions; however, there are some fundamental issues with your code that might be leading to your segfault
.
First, your signal handler code:
typedef void (*sighandler_t)(int);
sighandler_t f(int pid) {
void sigintHandler(int sig) {
printf("Process %d", pid);
}
return sigintHandler;
}
This is not standard C and even requires the -ftrampolines
flag be specified on some versions of gcc
to actually compile.
Your signal handler function itself has a few issues that need to be resolved:
sigintHandler
is a nested function, thus when your signal handler function f
returns by return sigintHandler;
, you're returning a function pointer.
In your code, this compiles correctly because you have typedef void (*sighandler_t)(int);
, which defines a function pointer type that can point to functions that have a void
return type and take an int
as a parameter, which your sigintHandler
is defined as.
Instead, your signal handler function could be written simply as:
void sigintHandler(int sig) {
printf("Signal %d\n", sig);
}
In your main function, you have the following:
if (signal(SIGTSTP, *f(1)) == SIG_ERR) {
// ....
}
Here it should be noted this as well has some issues. First, the signal
function takes as its first parameter the signal number (usually a macro defined in the signal.h
header) and as it's second argument a pointer to a function defined as void func_name(int sig)
.
To this, you are calling the function instead of passing it as a pointer.
*f(1)
actually makes a call to f
passing 1
as its parameter; instead, you would change it to the following:
if (signal(SIGTSTP, f) == SIG_ERR) {
// ....
}
But this should emit a warning/error since f
is defined as returning a function pointer instead of void
.
So to change the code to be compliant, you could just do the following:
#include <stdio.h>
#include <signal.h>
void sigintHandler(int sig) {
printf("Signal %d", sig);
}
int main(void) {
// ...
if (signal(SIGTSTP, sigintHandler) == SIG_ERR) {
// ...
}
// ...
return 0;
}
You stated however:
To have variable behaviour ...
This depends on what kind of variable nature you're intending, but if it's variable functions based on the signal, you can do something like the following:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sig_stop(int sig) {
printf("Process %d stop\n", getpid());
}
void sig_int(int sig) {
printf("Process %d interrupt\n", getpid());
}
int main(void) {
// ...
if (signal(SIGTSTP, sig_stop) == SIG_ERR) {
// ...
}
if (signal(SIGINT, sig_int) == SIG_ERR) {
// ...
}
// ...
return 0;
}
Or you could use a switch
statement:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigHandler(int sig) {
printf("Process %d received %d\n", getpid(), sig);
switch (sig) {
case SIGTSTP:
// do stop code
break;
case SIGINT:
// do interupt code
break;
}
}
int main(void) {
// ...
if (signal(SIGTSTP, sigHandler) == SIG_ERR) {
// ...
}
if (signal(SIGINT, sigHandler) == SIG_ERR) {
// ...
}
// ...
return 0;
}
any tips on how to debug seg faults in general would be really appreciated!
First, understand what a segmentation fault is; then you can use a debugger like gdb
to step through your code or inspect crash dumps to see where specifically the segfault
is happening.
Hope that can help.
Upvotes: 2
Reputation: 3443
aint sure about what you are asking, but i can help you understand your segmentation fault.
when you call a function there are several things that are done.
when 1,2, 6 are done by the Calling scope.
As you know, signal is a void arguments
hence the call (1) would push 0
arguments to the stack.
while the return (6) would pop your "unexistant" int
from the stack and corrupt it.
somewhat solution
you can't have signal function with parameters,
what you can is:
you can read your global variables within the signal function. and therefore read the current state of the program.
you can sys_call to get your process_id, thread_id.
i wouldn't recommend but you can read your stack further to the previous scope and get it's local variables. With BIG Note that it won't be the function you set the signal at... but the function that was running at the moment of the signal.
Upvotes: -1