diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 31 |
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 | */ |
342 | void __exit_signal(struct task_struct *tsk) | 342 | void __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 | } |