From dd12f48d4e8774415b528d3991ae47c28f26e1ac Mon Sep 17 00:00:00 2001 From: "Bhavesh P. Davda" Date: Wed, 17 Aug 2005 12:26:33 -0600 Subject: [PATCH] NPTL signal delivery deadlock fix This bug is quite subtle and only happens in a very interesting situation where a real-time threaded process is in the middle of a coredump when someone whacks it with a SIGKILL. However, this deadlock leaves the system pretty hosed and you have to reboot to recover. Not good for real-time priority-preemption applications like our telephony application, with 90+ real-time (SCHED_FIFO and SCHED_RR) processes, many of them multi-threaded, interacting with each other for high volume call processing. Acked-by: Roland McGrath Signed-off-by: Linus Torvalds --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/signal.c b/kernel/signal.c index ca1186eef938..d282fea81138 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -692,7 +692,7 @@ static void handle_stop_signal(int sig, struct task_struct *p) { struct task_struct *t; - if (p->flags & SIGNAL_GROUP_EXIT) + if (p->signal->flags & SIGNAL_GROUP_EXIT) /* * The process is in the middle of dying already. */ -- cgit v1.2.3 From 024f474795af7a0d41bd6d60061d78bd66d13f56 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 18 Aug 2005 11:24:19 -0700 Subject: [PATCH] Make RLIMIT_NICE ranges consistent with getpriority(2) As suggested by Michael Kerrisk , make RLIMIT_NICE consistent with getpriority before it becomes available in released glibc. Signed-off-by: Matt Mackall Acked-by: Ingo Molnar Acked-by: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'kernel') diff --git a/kernel/sched.c b/kernel/sched.c index a646e4f36c41..5f889d0cbfcc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3378,8 +3378,8 @@ EXPORT_SYMBOL(set_user_nice); */ int can_nice(const task_t *p, const int nice) { - /* convert nice value [19,-20] to rlimit style value [0,39] */ - int nice_rlim = 19 - nice; + /* convert nice value [19,-20] to rlimit style value [1,40] */ + int nice_rlim = 20 - nice; return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || capable(CAP_SYS_NICE)); } -- cgit v1.2.3 From 4c5640cb5f5a6fd780d99397eca028b575cb1206 Mon Sep 17 00:00:00 2001 From: David Meybohm Date: Mon, 22 Aug 2005 13:11:08 -0700 Subject: [PATCH] preempt race in getppid With CONFIG_PREEMPT && !CONFIG_SMP, it's possible for sys_getppid to return a bogus value if the parent's task_struct gets reallocated after current->group_leader->real_parent is read: asmlinkage long sys_getppid(void) { int pid; struct task_struct *me = current; struct task_struct *parent; parent = me->group_leader->real_parent; RACE HERE => for (;;) { pid = parent->tgid; #ifdef CONFIG_SMP { struct task_struct *old = parent; /* * Make sure we read the pid before re-reading the * parent pointer: */ smp_rmb(); parent = me->group_leader->real_parent; if (old != parent) continue; } #endif break; } return pid; } If the process gets preempted at the indicated point, the parent process can go ahead and call exit() and then get wait()'d on to reap its task_struct. When the preempted process gets resumed, it will not do any further checks of the parent pointer on !CONFIG_SMP: it will read the bad pid and return. So, the same algorithm used when SMP is enabled should be used when preempt is enabled, which will recheck ->real_parent in this case. Signed-off-by: David Meybohm Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel') diff --git a/kernel/timer.c b/kernel/timer.c index f2a11887a726..5377f40723ff 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1023,7 +1023,7 @@ asmlinkage long sys_getppid(void) parent = me->group_leader->real_parent; for (;;) { pid = parent->tgid; -#ifdef CONFIG_SMP +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) { struct task_struct *old = parent; -- cgit v1.2.3