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.