Re: 2.5.39: Signal delivery to thread groups: Bug or feature

Ingo Molnar (mingo@elte.hu)
Sun, 29 Sep 2002 12:27:11 +0200 (CEST)


On Sat, 28 Sep 2002, Axel wrote:

> The main signal dispatching function send_sig_info in kernel/signal.c
> requires at the moment an installed signal handler for delivery of
> signals to members of the thread group.

i fixed this bug, see the attached attached patch, it's against BK-curr.

It fixes the testcase Ulrich created from your description - does it fix
your testcase as well? (Ulrich added this testcase to NPTL, should show up
in the next drop.)

we still have one more problem left in the signal handling area: atomicity
of signal delivery. Eg. right now it's possible to have a signal 'in
flight' for one specific thread, which manages to block it before handling
the signal. What should the behavior be in that case? Does POSIX say
anything about this?

Ingo

--- linux/kernel/signal.c.orig Sun Sep 29 11:59:03 2002
+++ linux/kernel/signal.c Sun Sep 29 12:17:14 2002
@@ -874,9 +874,23 @@
return err;
}

+struct task_struct * find_unblocked_thread(struct task_struct *p, int signr)
+{
+ struct task_struct *tmp;
+ struct list_head *l;
+ struct pid *pid;
+
+ for_each_task_pid(p->tgid, PIDTYPE_TGID, tmp, l, pid)
+ if (!sigismember(&tmp->blocked, signr) &&
+ !sigismember(&tmp->real_blocked, signr))
+ return tmp;
+ return NULL;
+}
+
int
send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
+ struct task_struct *t;
unsigned long flags;
int ret = 0;

@@ -905,21 +919,19 @@
if (sig_ignored(p, sig))
goto out_unlock;

- /* blocked (or ptraced) signals get posted */
- spin_lock(&p->sigmask_lock);
- if ((p->ptrace & PT_PTRACED) || sigismember(&p->blocked, sig) ||
- sigismember(&p->real_blocked, sig)) {
- spin_unlock(&p->sigmask_lock);
+ if (sig_kernel_specific(sig))
goto out_send;
- }
- spin_unlock(&p->sigmask_lock);

+ /* Does any of the threads unblock the signal? */
+ t = find_unblocked_thread(p, sig);
+ if (!t) {
+ ret = __send_sig_info(sig, info, p, 1);
+ goto out_unlock;
+ }
if (sig_kernel_broadcast(sig) || sig_kernel_coredump(sig)) {
ret = __broadcast_thread_group(p, sig);
goto out_unlock;
}
- if (sig_kernel_specific(sig))
- goto out_send;

/* must not happen */
BUG();

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/