Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling signal after fork

Is there any difference between "code listing 1" and "code listing 2"? Because in Code Listing 1, the child process is able to catch the SIGTERM signal and exit nicely. But code listng 2 is terminating abruptly on SIGTERM signal.

I am using Linux and C.

Code Listing 1

if (signal(SIGTERM, stopChild) == SIG_ERR) {
    printf("Could not attach signal handler\n");
    return EXIT_FAILURE;
}
pid = fork();

Code Listing 2

pid = fork();
if (signal(SIGTERM, stopChild) == SIG_ERR) {
    printf("Could not attach signal handler\n");
    return EXIT_FAILURE;
}

The strange part is that in Code Listing 2, both child and parent process sets the signal handler for SIGTERM. So, this is supposed to work. Isn't it?

like image 565
Sabya Avatar asked Jan 28 '11 13:01

Sabya


People also ask

Is fork async signal safe?

POSIX specifies that fork can be called safely from signal handlers; it is required to be an async-signal-safe function.

What is Sigchld signal?

When a child process stops or terminates, SIGCHLD is sent to the parent process. The default response to the signal is to ignore it. The signal can be caught and the exit status from the child process can be obtained by immediately calling wait(2) and wait3(3C).


1 Answers

If you are sending the SIGTERM from the parent, the end result depends on the order on which processes get scheduled.

If the child gets scheduled first, everything works:

                                                +---------------+
                                                | pid = fork(); |
                                                +-------+-------+
                   parent                               |                               child
                          +-----------------------------+-----------------------------+
                          |                                                           |
                          |                                 +-------------------------+--------------------------+
                          |                                 | if (signal(SIGTERM, stopChild) == SIG_ERR) {       |
                          |                                 |       printf("Could not attach signal handler\n"); |
                          |                                 |       return EXIT_FAILURE;                         |
                          |                                 | }                                                  |
                          |                                 +-------------------------+--------------------------+
                          |                                                           |
                          .                                                           .
                          .                                                           .
                          .                                                           .
                          |                                                           |
+-------------------------+--------------------------+                                |
| if (signal(SIGTERM, stopChild) == SIG_ERR) {       |                                |
|       printf("Could not attach signal handler\n"); |                                |
|       return EXIT_FAILURE;                         |                                |
| }                                                  |                                |
+-------------------------+--------------------------+                                |
                          |                                                           |
                          |                                                           |
                          |                                                           |
            +-------------+-------------+                                             |
            | if (pid > 0) {            |                                             |
            |       kill(pid, SIGTERM); |                                             |
            | }                         |                                             |
            +-------------+-------------+                                             |
                          |                                                           |
                          |                                                           |
                          |                                                           |

But if the paren gets scheduled first, the child may have not had time to setup the signal handler:

                                                +---------------+
                                                | pid = fork(); |
                                                +-------+-------+
                   parent                               |                               child
                          +-----------------------------+-----------------------------+
                          |                                                           |
+-------------------------+--------------------------+                                |
| if (signal(SIGTERM, stopChild) == SIG_ERR) {       |                                |
|       printf("Could not attach signal handler\n"); |                                |
|       return EXIT_FAILURE;                         |                                |
| }                                                  |                                |
+-------------------------+--------------------------+                                |
                          |                                                           |
                          |                                                           |
                          |                                                           |
            +-------------+-------------+                                             |
            | if (pid > 0) {            |                                             |
            |       kill(pid, SIGTERM); |                                             |
            | }                         |                                             |
            +-------------+-------------+                                             |
                          |                                                           |
                          .                                                           .
                          .                                                           .
                          .                                                           .
                          |                                                           |
                          |                                 +-------------------------+--------------------------+
                          |                                 | if (signal(SIGTERM, stopChild) == SIG_ERR) {       |
                          |                                 |       printf("Could not attach signal handler\n"); |
                          |                                 |       return EXIT_FAILURE;                         |
                          |                                 | }                                                  |
                          |                                 +-------------------------+--------------------------+
                          |                                                           |
                          |                                                           |
                          |                                                           |

This is called a race condition, because the end result depends on who gets to run first.

like image 62
ninjalj Avatar answered Oct 24 '22 10:10

ninjalj