bottaio
bottaio

Reputation: 5093

Signal control in C

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?

Upvotes: 3

Views: 132

Answers (2)

Jean-Baptiste Yunès
Jean-Baptiste Yunès

Reputation: 36391

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).

Upvotes: 2

Thomas Dickey
Thomas Dickey

Reputation: 54505

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

Upvotes: 4

Related Questions