exit_state = leader->exit_state; 
 BUG_ON(leader->exit_state != EXIT_ZOMBIE); leader->exit_state = EXIT_DEAD; 
static inline int de_thread(struct task_struct *tsk){	struct signal_struct *sig = tsk->signal;	struct sighand_struct *newsighand, *oldsighand = tsk->sighand;	spinlock_t *lock = &oldsighand->siglock;	struct task_struct *leader = NULL;	int count;	/*	 * If we don't share sighandlers, then we aren't sharing anything	 * and we can just re-use it all.	 */	if (atomic_read(&oldsighand->count) <= 1) {		BUG_ON(atomic_read(&sig->count) != 1);		exit_itimers(sig);		return 0;	}	newsighand = kmem_cache_alloc(sighand_cachep, GFP_KERNEL);	if (!newsighand)		return -ENOMEM;	if (thread_group_empty(current))		goto no_thread_group;	/*	 * Kill all other threads in the thread group.	 * We must hold tasklist_lock to call zap_other_threads.	 */	read_lock(&tasklist_lock);	spin_lock_irq(lock);	if (sig->flags & SIGNAL_GROUP_EXIT) {		/*		 * Another group action in progress, just		 * return so that the signal is processed.		 */		spin_unlock_irq(lock);		read_unlock(&tasklist_lock);		kmem_cache_free(sighand_cachep, newsighand);		return -EAGAIN;	}	zap_other_threads(current);	read_unlock(&tasklist_lock);	/*	 * Account for the thread group leader hanging around:	 */	count = 1;	if (!thread_group_leader(current)) {		count = 2;		/*		 * The SIGALRM timer survives the exec, but needs to point		 * at us as the new group leader now.  We have a race with		 * a timer firing now getting the old leader, so we need to		 * synchronize with any firing (by calling del_timer_sync)		 * before we can safely let the old group leader die.		 */		sig->real_timer.data = (unsigned long)current;		spin_unlock_irq(lock);		if (del_timer_sync(&sig->real_timer))			add_timer(&sig->real_timer);		spin_lock_irq(lock);	}	while (atomic_read(&sig->count) > count) {		sig->group_exit_task = current;		sig->notify_count = count;		__set_current_state(TASK_UNINTERRUPTIBLE);		spin_unlock_irq(lock);		schedule();		spin_lock_irq(lock);	}	sig->group_exit_task = NULL;	sig->notify_count = 0;	spin_unlock_irq(lock);	/*	 * At this point all other threads have exited, all we have to	 * do is to wait for the thread group leader to become inactive,	 * and to assume its PID:	 */	if (!thread_group_leader(current)) {		struct task_struct *parent;		struct dentry *proc_dentry1, *proc_dentry2;		unsigned long exit_state, ptrace;		/*		 * Wait for the thread group leader to be a zombie.		 * It should already be zombie at this point, most		 * of the time.		 */		leader = current->group_leader;		while (leader->exit_state != EXIT_ZOMBIE)			yield();		spin_lock(&leader->proc_lock);		spin_lock(&current->proc_lock);		proc_dentry1 = proc_pid_unhash(current);		proc_dentry2 = proc_pid_unhash(leader);		write_lock_irq(&tasklist_lock);		BUG_ON(leader->tgid != current->tgid);		BUG_ON(current->pid == current->tgid);		/*		 * An exec() starts a new thread group with the		 * TGID of the previous thread group. Rehash the		 * two threads with a switched PID, and release		 * the former thread group leader:		 */		ptrace = leader->ptrace;		parent = leader->parent;		if (unlikely(ptrace) && unlikely(parent == current)) {			/*			 * Joker was ptracing his own group leader,			 * and now he wants to be his own parent!			 * We can't have that.			 */			ptrace = 0;		}		ptrace_unlink(current);		ptrace_unlink(leader);		remove_parent(current);		remove_parent(leader);		switch_exec_pids(leader, current);		current->parent = current->real_parent = leader->real_parent;		leader->parent = leader->real_parent = child_reaper;		current->group_leader = current;		leader->group_leader = leader;		add_parent(current, current->parent);		add_parent(leader, leader->parent);		if (ptrace) {			current->ptrace = ptrace;			__ptrace_link(current, parent);		}		list_del(&current->tasks);		list_add_tail(&current->tasks, &init_task.tasks);		current->exit_signal = SIGCHLD;		exit_state = leader->exit_state;		write_unlock_irq(&tasklist_lock);		spin_unlock(&leader->proc_lock);		spin_unlock(&current->proc_lock);		proc_pid_flush(proc_dentry1);		proc_pid_flush(proc_dentry2);		BUG_ON(exit_state != EXIT_ZOMBIE);        }	/*	 * There may be one thread left which is just exiting,	 * but it's safe to stop telling the group to kill themselves.	 */	sig->flags = 0;no_thread_group:	exit_itimers(sig);	if (leader)		release_task(leader);	BUG_ON(atomic_read(&sig->count) != 1);	if (atomic_read(&oldsighand->count) == 1) {		/*		 * Now that we nuked the rest of the thread group,		 * it turns out we are not sharing sighand any more either.		 * So we can just keep it.		 */		kmem_cache_free(sighand_cachep, newsighand);	} else {		/*		 * Move our state over to newsighand and switch it in.		 */		spin_lock_init(&newsighand->siglock);		atomic_set(&newsighand->count, 1);		memcpy(newsighand->action, oldsighand->action,		       sizeof(newsighand->action));		write_lock_irq(&tasklist_lock);		spin_lock(&oldsighand->siglock);		spin_lock(&newsighand->siglock);		current->sighand = newsighand;		recalc_sigpending();		spin_unlock(&newsighand->siglock);		spin_unlock(&oldsighand->siglock);		write_unlock_irq(&tasklist_lock);		if (atomic_dec_and_test(&oldsighand->count))			kmem_cache_free(sighand_cachep, oldsighand);	}	BUG_ON(!thread_group_leader(current));	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/962b564cf1ec8041e8890a3c3847e3a630a08f42/exec.c/buggy/fs/exec.c