diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-03-28 19:10:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-28 21:36:40 -0500 |
commit | 1434261c07bcebd5ef8b8a18f919fdee533b84e0 (patch) | |
tree | 1d0ba868866354569d2b8854a26ff48dbdbc1a98 | |
parent | fef23e7fbb11a0a78cd61935f7056bc2b237995a (diff) |
[PATCH] simplify exec from init's subthread
I think it is enough to take tasklist_lock for reading while changing
child_reaper:
Reparenting needs write_lock(tasklist_lock)
Only one thread in a thread group can do exec()
sighand->siglock garantees that get_signal_to_deliver()
will not see a stale value of child_reaper.
This means that we can change child_reaper earlier, without calling
zap_other_threads() twice.
"child_reaper = current" is a NOOP when init does exec from main thread, we
don't care.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/exec.c | 22 |
1 files changed, 10 insertions, 12 deletions
@@ -616,6 +616,15 @@ static int de_thread(struct task_struct *tsk) | |||
616 | kmem_cache_free(sighand_cachep, newsighand); | 616 | kmem_cache_free(sighand_cachep, newsighand); |
617 | return -EAGAIN; | 617 | return -EAGAIN; |
618 | } | 618 | } |
619 | |||
620 | /* | ||
621 | * child_reaper ignores SIGKILL, change it now. | ||
622 | * Reparenting needs write_lock on tasklist_lock, | ||
623 | * so it is safe to do it under read_lock. | ||
624 | */ | ||
625 | if (unlikely(current->group_leader == child_reaper)) | ||
626 | child_reaper = current; | ||
627 | |||
619 | zap_other_threads(current); | 628 | zap_other_threads(current); |
620 | read_unlock(&tasklist_lock); | 629 | read_unlock(&tasklist_lock); |
621 | 630 | ||
@@ -660,23 +669,12 @@ static int de_thread(struct task_struct *tsk) | |||
660 | struct dentry *proc_dentry1, *proc_dentry2; | 669 | struct dentry *proc_dentry1, *proc_dentry2; |
661 | unsigned long ptrace; | 670 | unsigned long ptrace; |
662 | 671 | ||
663 | leader = current->group_leader; | ||
664 | /* | ||
665 | * If our leader is the child_reaper become | ||
666 | * the child_reaper and resend SIGKILL signal. | ||
667 | */ | ||
668 | if (unlikely(leader == child_reaper)) { | ||
669 | write_lock(&tasklist_lock); | ||
670 | child_reaper = current; | ||
671 | zap_other_threads(current); | ||
672 | write_unlock(&tasklist_lock); | ||
673 | } | ||
674 | |||
675 | /* | 672 | /* |
676 | * Wait for the thread group leader to be a zombie. | 673 | * Wait for the thread group leader to be a zombie. |
677 | * It should already be zombie at this point, most | 674 | * It should already be zombie at this point, most |
678 | * of the time. | 675 | * of the time. |
679 | */ | 676 | */ |
677 | leader = current->group_leader; | ||
680 | while (leader->exit_state != EXIT_ZOMBIE) | 678 | while (leader->exit_state != EXIT_ZOMBIE) |
681 | yield(); | 679 | yield(); |
682 | 680 | ||