- task는 죽으면, 모든 resource를 release하지않고 왜 죽었는지 정도를 남겨둔다.
- 그 정보는 부모 task에서 자식의 죽음을 이용할때, 회수한다 예를 들면 join()
- do_noitfy_parent 는 task가 죽을때, 죽는 task의 부모에게 자식의 죽음을 알려주기 위한 함수이다
- do_notify_pidfd() 는 죽는 task의 FD에 대해서 죽는 event를 기다리는 task들을 깨워준다
- sig ID가 SIGCHLD가 아니더라도, parent == real_parent인 경우에는 sig ID를 SIGCHLD 로 바꿔준다.
- task->exit_code를 통해서 parent에게 왜 task가 죽었는지를 전달해준다, (info.si_code)
- 부모가 SIGCHLD 시그널을 받는다면, 부모에게 알려준다, __send_signal_locked().
- 만약 부모가 SIGCHLD 에 대해서 시그널을 안 받겠다고 해놨다면 (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN), 부모에게 알려주지않고 do_exit()에서 자체적으로 resource를 release한다
- 부모가 SIGCHLD를 안 받겠다고했지만, 부모가 자식의 죽음을 조사하는 과정에서 wait/blocked되어있는 race condition상황을 대비해서 부모를 깨워준다 (__wake_up_parent).
- 이 부분에 대해서 한번 확인해볼 필요가 있음. 20년 전 코드가 아직도 유효하고 필요한지.
/*
* Let a parent know about the death of a child.
* For a stopped/continued status change, use do_notify_parent_cldstop instead.
*
* Returns true if our parent ignored us and so we have switched to
* self-reaping.
*/
bool do_notify_parent(struct task_struct *tsk, int sig)
{
struct kernel_siginfo info;
unsigned long flags;
struct sighand_struct *psig;
bool autoreap = false;
u64 utime, stime;
WARN_ON_ONCE(sig == -1);
/* do_notify_parent_cldstop should have been called instead. */
WARN_ON_ONCE(task_is_stopped_or_traced(tsk));
WARN_ON_ONCE(!tsk->ptrace &&
(tsk->group_leader != tsk || !thread_group_empty(tsk)));
/*
* tsk is a group leader and has no threads, wake up the
* non-PIDFD_THREAD waiters.
*/
if (thread_group_empty(tsk))
do_notify_pidfd(tsk);
if (sig != SIGCHLD) {
/*
* This is only possible if parent == real_parent.
* Check if it has changed security domain.
*/
if (tsk->parent_exec_id != READ_ONCE(tsk->parent->self_exec_id))
sig = SIGCHLD;
}
clear_siginfo(&info);
info.si_signo = sig;
info.si_errno = 0;
/*
* We are under tasklist_lock here so our parent is tied to
* us and cannot change.
*
* task_active_pid_ns will always return the same pid namespace
* until a task passes through release_task.
*
* write_lock() currently calls preempt_disable() which is the
* same as rcu_read_lock(), but according to Oleg, this is not
* correct to rely on this
*/
rcu_read_lock();
info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(tsk->parent));
info.si_uid = from_kuid_munged(task_cred_xxx(tsk->parent, user_ns),
task_uid(tsk));
rcu_read_unlock();
task_cputime(tsk, &utime, &stime);
info.si_utime = nsec_to_clock_t(utime + tsk->signal->utime);
info.si_stime = nsec_to_clock_t(stime + tsk->signal->stime);
info.si_status = tsk->exit_code & 0x7f;
if (tsk->exit_code & 0x80)
info.si_code = CLD_DUMPED;
else if (tsk->exit_code & 0x7f)
info.si_code = CLD_KILLED;
else {
info.si_code = CLD_EXITED;
info.si_status = tsk->exit_code >> 8;
}
psig = tsk->parent->sighand;
spin_lock_irqsave(&psig->siglock, flags);
if (!tsk->ptrace && sig == SIGCHLD &&
(psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||
(psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {
/*
* We are exiting and our parent doesn't care. POSIX.1
* defines special semantics for setting SIGCHLD to SIG_IGN
* or setting the SA_NOCLDWAIT flag: we should be reaped
* automatically and not left for our parent's wait4 call.
* Rather than having the parent do it as a magic kind of
* signal handler, we just set this to tell do_exit that we
* can be cleaned up without becoming a zombie. Note that
* we still call __wake_up_parent in this case, because a
* blocked sys_wait4 might now return -ECHILD.
*
* Whether we send SIGCHLD or not for SA_NOCLDWAIT
* is implementation-defined: we do (if you don't want
* it, just use SIG_IGN instead).
*/
autoreap = true;
if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN)
sig = 0;
}
/*
* Send with __send_signal as si_pid and si_uid are in the
* parent's namespaces.
*/
if (valid_signal(sig) && sig)
__send_signal_locked(sig, &info, tsk->parent, PIDTYPE_TGID, false);
__wake_up_parent(tsk, tsk->parent);
spin_unlock_irqrestore(&psig->siglock, flags);
return autoreap;
}
'전공공부 > Linux' 카테고리의 다른 글
do_notify_parent_cldstop (0) | 2025.02.23 |
---|---|
setup_arch: arm64_memblock_init (0) | 2021.09.12 |
function: set_cpu_boot_mode_flag (0) | 2020.11.09 |
[2020.10.17] Linux Kernel, primary_entry - 1 (0) | 2020.10.21 |
[Line by line] Linux Kernel, SYM_CODE_START macro (0) | 2020.10.21 |