aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c31
1 files changed, 15 insertions, 16 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 54e9ef673e68..ca1fa854e469 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -341,24 +341,20 @@ void __exit_sighand(struct task_struct *tsk)
341 */ 341 */
342void __exit_signal(struct task_struct *tsk) 342void __exit_signal(struct task_struct *tsk)
343{ 343{
344 struct signal_struct * sig = tsk->signal; 344 struct signal_struct *sig = tsk->signal;
345 struct sighand_struct * sighand; 345 struct sighand_struct *sighand;
346
347 BUG_ON(!sig);
348 BUG_ON(!atomic_read(&sig->count));
346 349
347 if (!sig)
348 BUG();
349 if (!atomic_read(&sig->count))
350 BUG();
351 rcu_read_lock(); 350 rcu_read_lock();
352 sighand = rcu_dereference(tsk->sighand); 351 sighand = rcu_dereference(tsk->sighand);
353 spin_lock(&sighand->siglock); 352 spin_lock(&sighand->siglock);
353
354 posix_cpu_timers_exit(tsk); 354 posix_cpu_timers_exit(tsk);
355 if (atomic_dec_and_test(&sig->count)) { 355 if (atomic_dec_and_test(&sig->count))
356 posix_cpu_timers_exit_group(tsk); 356 posix_cpu_timers_exit_group(tsk);
357 tsk->signal = NULL; 357 else {
358 __exit_sighand(tsk);
359 spin_unlock(&sighand->siglock);
360 flush_sigqueue(&sig->shared_pending);
361 } else {
362 /* 358 /*
363 * If there is any task waiting for the group exit 359 * If there is any task waiting for the group exit
364 * then notify it: 360 * then notify it:
@@ -369,7 +365,6 @@ void __exit_signal(struct task_struct *tsk)
369 } 365 }
370 if (tsk == sig->curr_target) 366 if (tsk == sig->curr_target)
371 sig->curr_target = next_thread(tsk); 367 sig->curr_target = next_thread(tsk);
372 tsk->signal = NULL;
373 /* 368 /*
374 * Accumulate here the counters for all threads but the 369 * Accumulate here the counters for all threads but the
375 * group leader as they die, so they can be added into 370 * group leader as they die, so they can be added into
@@ -387,14 +382,18 @@ void __exit_signal(struct task_struct *tsk)
387 sig->nvcsw += tsk->nvcsw; 382 sig->nvcsw += tsk->nvcsw;
388 sig->nivcsw += tsk->nivcsw; 383 sig->nivcsw += tsk->nivcsw;
389 sig->sched_time += tsk->sched_time; 384 sig->sched_time += tsk->sched_time;
390 __exit_sighand(tsk); 385 sig = NULL; /* Marker for below. */
391 spin_unlock(&sighand->siglock);
392 sig = NULL; /* Marker for below. */
393 } 386 }
387
388 tsk->signal = NULL;
389 __exit_sighand(tsk);
390 spin_unlock(&sighand->siglock);
394 rcu_read_unlock(); 391 rcu_read_unlock();
392
395 clear_tsk_thread_flag(tsk,TIF_SIGPENDING); 393 clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
396 flush_sigqueue(&tsk->pending); 394 flush_sigqueue(&tsk->pending);
397 if (sig) { 395 if (sig) {
396 flush_sigqueue(&sig->shared_pending);
398 __cleanup_signal(sig); 397 __cleanup_signal(sig);
399 } 398 }
400} 399}