In C, linux, about kill signal and sleep() in loop

2019-07-29 05:26发布

问题:

I run my C program on Mac OS. Part of my program is as following. This code runs well on sigint signal but can't work on sigkill signal.

void sigkill(int sig){
    /*some code neglected*/
    exit(0);
}
void sigint(int sig){
    flag=1;
}

void alive(void) {
    signal(SIGINT, sigint);
    signal(SIGKILL, sigkill);
    alarm(10);
    while(1){
        //printf("%d\n",flag);
        sleep(1);
        if(flag==1){
            printf("no\n");
            flag=0;
        }
    }
}

I have four questions:

  1. At first I didn't write sleep(1), It can enter the function sigint(), and change the flag value, I can see from the printf. However, no "no" output as I expected.

  2. After I added sleep function, it works well. I suppose the while loop would check flag every 1 second, and output "no" if flag=1. However, it seems the "no" output everytime when I press ctrl+c. Why it don't wait for one second?

  3. The question said "You should not use 'sleep()' to wait 10 seconds. Use alarm(), coupled with a loop." I want to know how to implement this without sleep().

  4. The kill command can't invoke sigkill function, how to fix this?

回答1:

  1. In general, signals can only be "caught" by your application when it makes a system call into the kernel. If you do a plain while(1) { if (flag==1){...} }, that will never call into the kernel. Theoretically, when you do your outer printf in the while(1) loop, that should call into the kernel and so the signal could be caught.
  2. sleep() is interrupted by any signal. Check the man page for sleep(3).
  3. check the man page for alarm(2).
  4. You cannot change the signal handler for SIGKILL nor for SIGSTOP. These signal effects are hardcoded into the kernel. From sigaction(2):

    signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.

    The kill command with no arguments does not generate a SIGKILL signal; it generates SIGTERM.