- static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
- int group, int from_ancestor_ns)
- {
- struct sigpending *pending;
- struct sigqueue *q;
- int override_rlimit;
- int ret = 0, result;
-
- assert_spin_locked(&t->sighand->siglock);
-
- result = TRACE_SIGNAL_IGNORED;
- if (!prepare_signal(sig, t,
- from_ancestor_ns || (info == SEND_SIG_FORCED)))
- goto ret;
-
- pending = group ? &t->signal->shared_pending : &t->pending;
- /*
- * Short-circuit ignored signals and support queuing
- * exactly one non-rt signal, so that we can get more
- * detailed information about the cause of the signal.
- */
- result = TRACE_SIGNAL_ALREADY_PENDING;
- if (legacy_queue(pending, sig)) //如果是低于32的信号,并且已经在pending中出现了的信号,就直接返回了,ignore
- goto ret;
-
- result = TRACE_SIGNAL_DELIVERED;
- /*
- * fast-pathed signals for kernel-internal things like SIGSTOP
- * or SIGKILL.
- */
- if (info == SEND_SIG_FORCED)
- goto out_set;
-
- /*
- * Real-time signals must be queued if sent by sigqueue, or
- * some other real-time mechanism. It is implementation
- * defined whether kill() does so. We attempt to do so, on
- * the principle of least surprise, but since kill is not
- * allowed to fail with EAGAIN when low on memory we just
- * make sure at least one signal gets delivered and don't
- * pass on the info struct.
- */
- if (sig < SIGRTMIN)
- override_rlimit = (is_si_special(info) || info->si_code >= 0);
- else
- override_rlimit = 0;
//分配sigqueue结构,并且链入到相应的pending。
- q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,
- override_rlimit);
- if (q) {
- list_add_tail(&q->list, &pending->list);
- switch ((unsigned long) info) {
- case (unsigned long) SEND_SIG_NOINFO:
- q->info.si_signo = sig;
- q->info.si_errno = 0;
- q->info.si_code = SI_USER;
- q->info.si_pid = task_tgid_nr_ns(current,
- task_active_pid_ns(t));
- q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
- break;
- case (unsigned long) SEND_SIG_PRIV:
- q->info.si_signo = sig;
- q->info.si_errno = 0;
- q->info.si_code = SI_KERNEL;
- q->info.si_pid = 0;
- q->info.si_uid = 0;
- break;
- default:
- copy_siginfo(&q->info, info);
- if (from_ancestor_ns)
- q->info.si_pid = 0;
- break;
- }
-
- userns_fixup_signal_uid(&q->info, t);
-
- } else if (!is_si_special(info)) {
- if (sig >= SIGRTMIN && info->si_code != SI_USER) {
- /*
- * Queue overflow, abort. We may abort if the
- * signal was rt and sent by user using something
- * other than kill().
- */
- result = TRACE_SIGNAL_OVERFLOW_FAIL;
- ret = -EAGAIN;
- goto ret;
- } else {
- /*
- * This is a silent loss of information. We still
- * send the signal, but the *info bits are lost.
- */
- result = TRACE_SIGNAL_LOSE_INFO;
- }
- }
-
- out_set:
- signalfd_notify(t, sig);
- sigaddset(&pending->signal, sig); //加入位图
- complete_signal(sig, t, group);
- ret:
- trace_signal_generate(sig, info, t, group, result);
- return ret;
- }
-
- static inline int legacy_queue(struct sigpending *signals, int sig)
- {
- return (sig < SIGRTMIN) && sigismember(&signals->signal, sig); //是不可靠信号,并且该信号已经存在挂起信号,