The calling signal after fork

Is there a difference between a "code 1 list" and a "code 2"? Because in Listing 1, the child process is able to catch the SIGTERM signal and exit beautifully. But listng 2 code is abruptly interrupted by a SIGTERM signal.

I use Linux and C.

Listing 1

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

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 Listing 2, both the child and the parent processes define a signal handler for SIGTERM . So this should work. Is not it?

+6
c linux signals fork signal-handling
source share
3 answers

If you send SIGTERM from the parent, the final result depends on the order in which the processes are planned.

If the child is first scheduled, 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 you assign a guy first, the child may not have time to configure 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 starts first.

+5
source share

Firstly, signal () is deprecated, it is better to use sigaction () . I don't think fork () might completely disappear, as many use it, but sigaction () does provide a nicer interface.

The behavior you experience is usually caused by calling fork () from the stream. POSIX addresses this:

A process must be created using a single thread. If a multi-threaded process calls fork (), the new process should contain a replica of the thread's call and its entire address space, possibly including the state of the mutexes and other resources. Therefore, to avoid errors, the child process can only perform asynchronous signaling operations until such time as one of the exec functions is called. [THR] Fork handlers can be set using pthread_atfork () to support application invariants in fork ().

When an application calls fork () from a signal handler and any fork of handlers registered by pthread_atfork () calls a function that is not safe for an asynchronous signal, the behavior is undefined.

This means that instead of inheriting a copy of the full address space of the parent, you only inherit a copy of the address space of the calling streams that does not contain your handlers. It is possible that you are really (perhaps even involuntarily) calling fork () from the stream.

The child process receives a copy of the copy of the parent address space. The only difference from signals is that they are waiting for a signal that the child will not receive, because he receives a set of signals initialized to zero. But yes, it gets a copy of the handlers.

+3
source share

Well, according to the person, the plug:

The fork (), fork1 (), and forkall () functions create a new process. The address space of the new process (child process) is an exact copy of the address space of the calling process (parent process). The child process inherits the following attributes of the parent process:

...

o signal processing settings (i.e. SIG_DFL, SIG_IGN, SIG_HOLD, function address)

In the first example, the signal handler will be copied from the context of the parent to the forked child. But I can’t explain why in the second example the installation of the signal handler in the child case would fail.

0
source share

All Articles