aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/exec.c11
-rw-r--r--include/linux/pid.h2
-rw-r--r--kernel/pid.c9
3 files changed, 15 insertions, 7 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 54135df2a966..b7aa3d6422d6 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -696,23 +696,20 @@ static int de_thread(struct task_struct *tsk)
696 */ 696 */
697 697
698 /* Become a process group leader with the old leader's pid. 698 /* Become a process group leader with the old leader's pid.
699 * Note: The old leader also uses thispid until release_task 699 * The old leader becomes a thread of the this thread group.
700 * Note: The old leader also uses this pid until release_task
700 * is called. Odd but simple and correct. 701 * is called. Odd but simple and correct.
701 */ 702 */
702 detach_pid(current, PIDTYPE_PID); 703 detach_pid(current, PIDTYPE_PID);
703 current->pid = leader->pid; 704 current->pid = leader->pid;
704 attach_pid(current, PIDTYPE_PID, current->pid); 705 attach_pid(current, PIDTYPE_PID, current->pid);
705 attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); 706 transfer_pid(leader, current, PIDTYPE_PGID);
706 attach_pid(current, PIDTYPE_SID, current->signal->session); 707 transfer_pid(leader, current, PIDTYPE_SID);
707 list_replace_rcu(&leader->tasks, &current->tasks); 708 list_replace_rcu(&leader->tasks, &current->tasks);
708 709
709 current->group_leader = current; 710 current->group_leader = current;
710 leader->group_leader = current; 711 leader->group_leader = current;
711 712
712 /* Reduce leader to a thread */
713 detach_pid(leader, PIDTYPE_PGID);
714 detach_pid(leader, PIDTYPE_SID);
715
716 current->exit_signal = SIGCHLD; 713 current->exit_signal = SIGCHLD;
717 714
718 BUG_ON(leader->exit_state != EXIT_ZOMBIE); 715 BUG_ON(leader->exit_state != EXIT_ZOMBIE);
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 29960b03bef7..93da7e2d9f30 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task,
76 enum pid_type type, int nr)); 76 enum pid_type type, int nr));
77 77
78extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type)); 78extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
79extern void FASTCALL(transfer_pid(struct task_struct *old,
80 struct task_struct *new, enum pid_type));
79 81
80/* 82/*
81 * look up a PID in the hash table. Must be called with the tasklist_lock 83 * look up a PID in the hash table. Must be called with the tasklist_lock
diff --git a/kernel/pid.c b/kernel/pid.c
index 93e212f20671..6db82b68e2f8 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -252,6 +252,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type)
252 free_pid(pid); 252 free_pid(pid);
253} 253}
254 254
255/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
256void fastcall transfer_pid(struct task_struct *old, struct task_struct *new,
257 enum pid_type type)
258{
259 new->pids[type].pid = old->pids[type].pid;
260 hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
261 old->pids[type].pid = NULL;
262}
263
255struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type) 264struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
256{ 265{
257 struct task_struct *result = NULL; 266 struct task_struct *result = NULL;