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