3

Is it possible to assure signal invoking order in C? Let's look at the following code:

//main.c
int counter;
pid_t pid;

void alrm_handler(int s)
{
    kill(pid, SIGUSR1);
    alarm(1);
    --counter;
    if (counter == 0)
        kill(pid, SIGTERM);
    printf("%d\n", counter);
    fflush(stdout);
}

int main(int argc, char* argv[])
{
    counter = atoi(argv[1]);
    signal(SIGALRM, alrm_handler);
    alarm(1);

    pid = fork();
    if (!pid)
        execl("child", "child", NULL);

    wait(NULL);

    return 0;
}

//child.c
void usr1_handler(int s)
{
    puts("TEXT");
    fflush(stdout);
}

int main()
{
    signal(SIGUSR1, usr1_handler);

    while(1)
    {
        struct timespec T;
        T.tv_nsec = 100;
        T.tv_sec = 0;
        nanosleep(&T, NULL);
    }

    return 0;
}

Even though I send SIG_USR1 3 times I get an output only 2 times. It seems that SIGTERM has higher priority or something. How is it possible to achieve 3 outputs in this scenario?

bottaio
  • 4,963
  • 3
  • 19
  • 43
  • posted code implements a nested/recursive signal handler That is a no-no. The posted code implements a call to I/O function `printf()` That is a no-no. the first posted code improperly handles the returned value from fork() and seems to expect that the call to execl() will never fail. – user3629249 Oct 26 '15 at 12:09
  • I am not asking about mistakes that this code has (I've omitted some things for simplicity). All I am asking for is a way to ensure that sigterm will not arrive before sigusr1. I think that it is not always possible. SIGTERM might have bigger priority than SIGUSR1 and that's why they arrive in this order. – bottaio Oct 26 '15 at 22:01
  • most of the programmers to this web site are 'new' and would not know a 'mistake from a chilli pepper. SO I try to indicate coding problems, outside the scope of the actual question, so the 'new' programmer can learn – user3629249 Oct 27 '15 at 21:18

2 Answers2

4

One problem with your sample programs, which will affect the order of output, is that you are using buffered-I/O in the signal handlers. Besides being unsafe, the operations do not necessarily complete in the order you expect.

For discussion, see

Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
2

The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition:

The order in which multiple, simultaneously pending signals outside the range SIGRTMIN to SIGRTMAX are delivered to or accepted by a process is unspecified.

Your parent process run so fast that it probably sends SIGUSR1 and SIGTERM before the child being able to receive it, so the child has two pending signals and the order is unspecified (read implementation defined -- any order is possible).

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69