Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[pandora-kernel.git] / kernel / signal.c
index c088011..a4077e9 100644 (file)
@@ -3066,18 +3066,39 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
 }
 #endif
 
+/*
+ * For kthreads only, must not be used if cloned with CLONE_SIGHAND
+ */
+void kernel_sigaction(int sig, __sighandler_t action)
+{
+       spin_lock_irq(&current->sighand->siglock);
+       current->sighand->action[sig - 1].sa.sa_handler = action;
+       if (action == SIG_IGN) {
+               sigset_t mask;
+
+               sigemptyset(&mask);
+               sigaddset(&mask, sig);
+
+               flush_sigqueue_mask(&mask, &current->signal->shared_pending);
+               flush_sigqueue_mask(&mask, &current->pending);
+               recalc_sigpending();
+       }
+       spin_unlock_irq(&current->sighand->siglock);
+}
+EXPORT_SYMBOL(kernel_sigaction);
+
 int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 {
-       struct task_struct *t = current;
+       struct task_struct *p = current, *t;
        struct k_sigaction *k;
        sigset_t mask;
 
        if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))
                return -EINVAL;
 
-       k = &t->sighand->action[sig-1];
+       k = &p->sighand->action[sig-1];
 
-       spin_lock_irq(&current->sighand->siglock);
+       spin_lock_irq(&p->sighand->siglock);
        if (oact)
                *oact = *k;
 
@@ -3096,17 +3117,16 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
                 *   (for example, SIGCHLD), shall cause the pending signal to
                 *   be discarded, whether or not it is blocked"
                 */
-               if (sig_handler_ignored(sig_handler(t, sig), sig)) {
+               if (sig_handler_ignored(sig_handler(p, sig), sig)) {
                        sigemptyset(&mask);
                        sigaddset(&mask, sig);
-                       flush_sigqueue_mask(&mask, &t->signal->shared_pending);
-                       do {
+                       flush_sigqueue_mask(&mask, &p->signal->shared_pending);
+                       for_each_thread(p, t)
                                flush_sigqueue_mask(&mask, &t->pending);
-                       } while_each_thread(current, t);
                }
        }
 
-       spin_unlock_irq(&current->sighand->siglock);
+       spin_unlock_irq(&p->sighand->siglock);
        return 0;
 }