Question

I am working in C language. I am trying to catch and process two different signals:

  • INT: when this signal is caught, action1 or action2 is triggered
  • QUIT: when this signal is caught, the INT signal action is switched (action1->action2 or action2->action1)

Default INT signal action is set to action1.

In my code,switchaction function is well triggered by QUIT signal, but has no effect on INT signal action :s

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

typedef void (*sighandler_t)(int);
sighandler_t prev_handler;

void action1(int n){
  printf("First message\n");
}
void action2(int n){
  printf("Second message\n");
}

void switchaction(int n){
  printf("Switch action\n");
  prev_handler=action2;
}

int main() {
  prev_handler = action1;
  printf("PID: %d\n", getpid());
  prev_handler= signal(SIGINT,prev_handler);
  signal(SIGQUIT,switchaction);

  travail(); //This function never ends
}

Would you have any idea of what is wrong in my code ?

Thanks,

Yann

Was it helpful?

Solution

Your syscall

prev_handler= signal(SIGINT,prev_handler);

is setting the signal handler to the value of prev_handler variable at the moment you are executing the signal syscall. Changing (after) the value of prev_handler does not change the handling of SIGINT signal. In other words, signal (and most C calls) have a call by value semantics. If you call signal once, the kernel keep the same handler (till you call signal again with the same signal number, or till you call sigaction(2) etc...).

Read carefully (assuming you are on Linux) the signal(7) and signal(2) man pages.

I would instead define

volatile sig_atomic_t howhandle;

void switchaction(int n __attribute__((unused))) {
    if (howhandle) 
       howhandle = 0;
    else 
       howhandle = 1;
}

void handleint (int n) {
    if (howhandle) action1(n); else action2(n);
}

and install just

signal(SIGINT, handleint);
signal(SIGQUIT, switchaction);

Also, notice that calling printf inside a handler is incorrect (because printf is not an async-signal-safe function, but you call it in action1, called by handleint...). Read again signal(7)

You should have some other volatile sig_atomic_t variables and test (and clear them) at appropriate places inside your travail working function, but set them only in your signal handlers. Setting a volatile sig_atomic_t variable is pretty much the only thing you can do reliably inside a signal handler.

If you accept Linux specific solutions learn more about signalfd(2) (and use also poll(2)...). Read also Advanced Linux Programming.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top