/* * When we hit the race with PTRACE_ATTACH, * we will not report this child.  But the * race means it has not yet been moved to * our ptrace_children list, so we need to * set the flag here to avoid a spurious ECHILD * when the race happens with the only child. */ flag = 1; 
static long do_wait(pid_t pid, int options, struct siginfo __user *infop,		    int __user *stat_addr, struct rusage __user *ru){	DECLARE_WAITQUEUE(wait, current);	struct task_struct *tsk;	int flag, retval;	add_wait_queue(&current->signal->wait_chldexit,&wait);repeat:	/*	 * We will set this flag if we see any child that might later	 * match our criteria, even if we are not able to reap it yet.	 */	flag = 0;	current->state = TASK_INTERRUPTIBLE;	read_lock(&tasklist_lock);	tsk = current;	do {		struct task_struct *p;		struct list_head *_p;		int ret;		list_for_each(_p,&tsk->children) {			p = list_entry(_p,struct task_struct,sibling);			ret = eligible_child(pid, options, p);			if (!ret)				continue;			switch (p->state) {			case TASK_TRACED:				if (!my_ptrace_child(p))					continue;				/*FALLTHROUGH*/			case TASK_STOPPED:				/*				 * It's stopped now, so it might later				 * continue, exit, or stop again.				 */				flag = 1;				if (!(options & WUNTRACED) &&				    !my_ptrace_child(p))					continue;				retval = wait_task_stopped(p, ret == 2,							   (options & WNOWAIT),							   infop,							   stat_addr, ru);				if (retval == -EAGAIN)					goto repeat;				if (retval != 0) /* He released the lock.  */					goto end;				break;			default:			// case EXIT_DEAD:				if (p->exit_state == EXIT_DEAD)					continue;			// case EXIT_ZOMBIE:				if (p->exit_state == EXIT_ZOMBIE) {					/*					 * Eligible but we cannot release					 * it yet:					 */					if (ret == 2)						goto check_continued;					if (!likely(options & WEXITED))						continue;					retval = wait_task_zombie(						p, (options & WNOWAIT),						infop, stat_addr, ru);					/* He released the lock.  */					if (retval != 0)						goto end;					break;				}check_continued:				/*				 * It's running now, so it might later				 * exit, stop, or stop and then continue.				 */				flag = 1;				if (!unlikely(options & WCONTINUED))					continue;				retval = wait_task_continued(					p, (options & WNOWAIT),					infop, stat_addr, ru);				if (retval != 0) /* He released the lock.  */					goto end;				break;			}		}		if (!flag) {			list_for_each(_p, &tsk->ptrace_children) {				p = list_entry(_p, struct task_struct,						ptrace_list);				if (!eligible_child(pid, options, p))					continue;				flag = 1;				break;			}		}		if (options & __WNOTHREAD)			break;		tsk = next_thread(tsk);		if (tsk->signal != current->signal)			BUG();	} while (tsk != current);	read_unlock(&tasklist_lock);	if (flag) {		retval = 0;		if (options & WNOHANG)			goto end;		retval = -ERESTARTSYS;		if (signal_pending(current))			goto end;		schedule();		goto repeat;	}	retval = -ECHILD;end:	current->state = TASK_RUNNING;	remove_wait_queue(&current->signal->wait_chldexit,&wait);	if (infop) {		if (retval > 0)		retval = 0;		else {			/*			 * For a WNOHANG return, clear out all the fields			 * we would set so the user can easily tell the			 * difference.			 */			if (!retval)				retval = put_user(0, &infop->si_signo);			if (!retval)				retval = put_user(0, &infop->si_errno);			if (!retval)				retval = put_user(0, &infop->si_code);			if (!retval)				retval = put_user(0, &infop->si_pid);			if (!retval)				retval = put_user(0, &infop->si_uid);			if (!retval)				retval = put_user(0, &infop->si_status);		}	}	return retval;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/7f2a52555998c699a7e89f24636c909d6fc08a60/exit.c/buggy/kernel/exit.c