]> Pileus Git - ~andy/linux/blobdiff - kernel/signal.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
[~andy/linux] / kernel / signal.c
index 24be82c0aae36ea636f8c346a67b7abcf7323590..72bb4f51f9634c448ad6eb4986d8ed7f35deb1f1 100644 (file)
@@ -551,9 +551,7 @@ static int check_kill_permission(int sig, struct siginfo *info,
            !capable(CAP_KILL)) {
                switch (sig) {
                case SIGCONT:
-                       read_lock(&tasklist_lock);
                        sid = task_session(t);
-                       read_unlock(&tasklist_lock);
                        /*
                         * We don't return the error if sid == NULL. The
                         * task was unhashed, the caller must notice this.
@@ -730,7 +728,8 @@ static void complete_signal(int sig, struct task_struct *p, int group)
         * Found a killable thread.  If the signal will be fatal,
         * then start taking the whole group down immediately.
         */
-       if (sig_fatal(p, sig) && !(signal->flags & SIGNAL_GROUP_EXIT) &&
+       if (sig_fatal(p, sig) &&
+           !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
            !sigismember(&t->real_blocked, sig) &&
            (sig == SIGKILL || !(t->ptrace & PT_PTRACED))) {
                /*
@@ -893,7 +892,8 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
  * since we do not want to have a signal handler that was blocked
  * be invoked when user space had explicitly blocked it.
  *
- * We don't want to have recursive SIGSEGV's etc, for example.
+ * We don't want to have recursive SIGSEGV's etc, for example,
+ * that is why we also clear SIGNAL_UNKILLABLE.
  */
 int
 force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
@@ -913,6 +913,8 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
                        recalc_sigpending_and_wake(t);
                }
        }
+       if (action->sa.sa_handler == SIG_DFL)
+               t->signal->flags &= ~SIGNAL_UNKILLABLE;
        ret = specific_send_sig_info(sig, info, t);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
@@ -1617,7 +1619,8 @@ static int do_signal_stop(int signr)
        } else {
                struct task_struct *t;
 
-               if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
+               if (unlikely((sig->flags & (SIGNAL_STOP_DEQUEUED | SIGNAL_UNKILLABLE))
+                                        != SIGNAL_STOP_DEQUEUED) ||
                    unlikely(signal_group_exit(sig)))
                        return 0;
                /*
@@ -1763,7 +1766,8 @@ relock:
                /*
                 * Global init gets no signals it doesn't want.
                 */
-               if (is_global_init(current))
+               if (unlikely(signal->flags & SIGNAL_UNKILLABLE) &&
+                   !signal_group_exit(signal))
                        continue;
 
                if (sig_kernel_stop(signr)) {
@@ -2537,7 +2541,7 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */