Send SIGTERM signal to a process kernel processing flow

Send SIGTERM signal to a process kernel processing flow

 

Take sending SIGTERM signal to a process under the command line as an example to illustrate how the kernel processes this signal

First, a sigqueue will be alloc ated, which represents SIGTERM, and then the sigqueue will be inserted into the pending list of the target process;

Then in complete_ In signal(), because SIGTERM is sig_fatal signal, so it will traverse all threads in the process, set SIGKILL on the pending signal set of each thread, and set the task of the process_ Signal of struct_ Set the flag value of struct to SIGNAL_GROUP_EXIT

Then, each thread in the process processes the SIGKILL signal and gets it_ In signal (), because of the task of the process_ struct. signal_ struct. Flag value is SIGNAL_GROUP_EXIT, so signal_ group_ The exit () condition is true, so do will be called_ group_ Exit (ksig - > info. Si_signo) directly exit yourself. There are two case s for this exit flow:

1. For non main threads, click exit_ Exit of thread in notify()_ State will be set to EXIT_DEAD, and then call release directly_ Task(), this function sets a free task_ rcu callback of struct, and the task of this thread will be_ Struct structure free

2. For the main thread, click exit_notify() will determine the thread of this thread_ Whether the group linked list is empty. If it is empty, it means that other threads in the process exit, and then call do_notify_parent(), this function sends sigcld signal to the parent process. This function returns true, indicating that the parent process ignores the sigcld signal; If false is returned, it indicates that the parent process has not ignored the SIGCHLD signal. If true is returned, the task of the main thread_ struct. exit_ State will be set to EXIT_DEAD, and then call release directly like the non main thread_ task(); If false is returned, the task of the main thread_ struct. exit_ State will be set to EXIT_ZOMBIE, you will not call release at this time_ Task() go to free task_struct, but wait for the parent process's wait series system call to free (call release in wait_task_zombie())_ Task() free)

 

Note:

All threads in the same process share the same signal_struct, this is in copy_ It can be seen from signal () that if clone_ Clone in flags_ When thread flag is, the current thread will not be assigned a signal_struct, but through dup_task_struct() to the task of this thread_ struct. signal_ The struct pointer is consistent with current, which is the main thread, and signal_struct will only allocate to the main thread, that is, when fork ing a new process.

 

The main thread processes SIGKILL signal flow

[   71.000794] CPU: 1 PID: 2802 Comm: xxx Tainted: P           O      4.19.116+ #79
[   71.000797] Hardware name: xxx (DT)
[   71.000800] Call trace:
[   71.000806] dump_backtrace+0x0/0x4
[   71.000812] dump_stack+0xf4/0x134
[   71.000817] get_signal+0xb7c/0xf68
[   71.000824] do_notify_resume+0x130/0x24a0
[   71.000829] work_pending+0x8/0x10

 

Non main thread processing SIGKILL signal flow

[   71.000835] CPU: 0 PID: 2862 Comm: HwBinder:2802_1 Tainted: P           O      4.19.116+ #79
[   71.000840] Hardware name: xxx (DT)
[   71.000843] Call trace:
[   71.000849] dump_backtrace+0x0/0x4
[   71.000854] dump_stack+0xf4/0x134
[   71.000859] get_signal+0xb7c/0xf68
[   71.000865] do_notify_resume+0x130/0x24a0
[   71.000869] work_pending+0x8/0x10

 

 

Task of main thread_ Struct is callstack of free:

[   71.004888] CPU: 2 PID: 1 Comm: init Tainted: P           O      4.19.116+ #79
[   71.004893] Hardware name: xxx (DT)
[   71.004896] Call trace:
[   71.004906] dump_backtrace+0x0/0x4
[   71.004915] dump_stack+0xf4/0x134
[   71.004921] release_task+0xaa0/0xac4
[   71.004926] wait_consider_task+0x6f0/0xde8
[   71.004932] do_wait+0x1bc/0x2e0
[   71.004937] kernel_wait4+0x13c/0x2c8
[   71.004941] __arm64_sys_wait4+0x44/0xe4
[   71.004949] el0_svc_common+0xb8/0x1b8
[   71.004954] el0_svc_handler+0x74/0x90
[   71.004958] el0_svc+0x8/0x340

 

Non main thread task_struct is callstack of free:

[   71.001001] CPU: 0 PID: 2862 Comm: HwBinder:2802_1 Tainted: P           O      4.19.116+ #79
[   71.001004] Hardware name: xxx (DT)
[   71.001007] Call trace:
[   71.001012] dump_backtrace+0x0/0x4
[   71.001018] dump_stack+0xf4/0x134
[   71.001023] release_task+0xaa0/0xac4
[   71.001028] do_exit+0x140c/0x1974
[   71.001033] do_group_exit+0x5fc/0x640
[   71.001037] do_signal_stop+0x0/0x45c
[   71.001042] do_notify_resume+0x130/0x24a0
[   71.001047] work_pending+0x8/0x10

 

Added by David Wood on Thu, 27 Jan 2022 12:58:39 +0200