Exemplo n.º 1
0
/*  wait till none of the processes in the stack starting at k is live */
int
waitstack(int k)
{
int npending, status, totstatus;
int i;

totstatus = 0;
npending = 0;
for(i=k ; i<nproc; ++i)
	if(! procstack[i].done)
		++npending;
enbint(SIG_IGN);
if(dbgflag > 1)
	printf("waitstack(%d)\n", k);

while(npending>0 && proclive>0)
	{
	if(waitproc(&status) >= k)
		--npending;
	totstatus |= status;
	}

if(nproc > k)
	nproc = k;
enbint(intrupt);
return totstatus;
}
Exemplo n.º 2
0
/*
 * Check to see if any children have exited, and if so, read any unread
 * input and then remove the child from the list of children.
 */
static void
reap(int dummy)
{
	CHILD *pc;
	int save_errno = errno;
	int status = 0;
	pid_t pid;

	debugmsg(DM_CALL, "reap() called\n");

	/*
	 * Reap every child that has exited.  Break out of the
	 * loop as soon as we run out of children that have
	 * exited so far.
	 */
	for ( ; ; ) {
		/*
		 * Do a non-blocking check for exiting processes
		 */
		pid = waitproc(&status, FALSE);
		debugmsg(DM_MISC, 
			 "reap() pid = %d status = %d activechildren=%d\n",
			 pid, status, activechildren);

		/*
		 * See if a child really exited
		 */
		if (pid == 0)
			break;
		if (pid < 0) {
			if (errno != ECHILD)
				error("Wait failed: %s", SYSERR);
			break;
		}

		/*
		 * Find the process (pid) and mark it as dead.
		 */
		for (pc = childlist; pc; pc = pc->c_next)
			if (pc->c_pid == pid) {
				needscan = TRUE;
				pc->c_state = PSdead;
			}

	}

	/*
	 * Reset signals
	 */
	(void) signal(SIGCHLD, reap);

	debugmsg(DM_CALL, "reap() done\n");
	errno = save_errno;
}
Exemplo n.º 3
0
int
dosys(char *comstring, int nohalt, int nowait, char *prefix)
{
int status;
struct process *procp;

/* make sure there is room in the process stack */
if(nproc >= MAXPROC)
	waitstack(MAXPROC-1);

/* make sure fewer than proclimit processes are running */
while(proclive >= proclimit)
	{
	enbint(SIG_IGN);
	waitproc(&status);
	enbint(intrupt);
	}

if(prefix)
	{
	fputs(prefix, stdout);
	fputs(comstring, stdout);
	}

procp = procstack + nproc;
procp->pid = (forceshell || metas(comstring) ) ?
	doshell(comstring,nohalt) : doexec(comstring);
if(procp->pid == -1)
	fatal("fork failed");
procstack[nproc].nohalt = nohalt;
procstack[nproc].nowait = nowait;
procstack[nproc].done = NO;
++proclive;
++nproc;

if(nowait)
	{
	printf(" &%d\n", procp->pid);
	fflush(stdout);
	return 0;
	}
if(prefix)
	{
	putchar('\n');
	fflush(stdout);
	}
return waitstack(nproc-1);
}
Exemplo n.º 4
0
STATIC int
dowait(int flags, struct job *job)
{
	int pid;
	int status;
	struct procstat *sp;
	struct job *jp;
	struct job *thisjob;
	int done;
	int stopped;
	extern volatile char gotsig[];

	TRACE(("dowait(%x) called\n", flags));
	do {
		pid = waitproc(flags & WBLOCK, job, &status);
		TRACE(("wait returns pid %d, status %d\n", pid, status));
	} while (pid == -1 && errno == EINTR && gotsig[SIGINT - 1] == 0);
	if (pid <= 0)
		return pid;
	INTOFF;
	thisjob = NULL;
	for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
		if (jp->used) {
			done = 1;
			stopped = 1;
			for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
				if (sp->pid == -1)
					continue;
				if (sp->pid == pid) {
					TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status));
					sp->status = status;
					thisjob = jp;
				}
				if (sp->status == -1)
					stopped = 0;
				else if (WIFSTOPPED(sp->status))
					done = 0;
			}
			if (stopped) {		/* stopped or done */
				int state = done ? JOBDONE : JOBSTOPPED;
				if (jp->state != state) {
					TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
					jp->state = state;
#if JOBS
					if (done)
						set_curjob(jp, 0);
#endif
				}
			}
		}
	}

	if (thisjob && thisjob->state != JOBRUNNING) {
		int mode = 0;
		if (!rootshell || !iflag)
			mode = SHOW_SIGNALLED;
		if ((job == thisjob && (flags & WNOFREE) == 0) ||
		    (job != thisjob && (flags & WNOFREE) != 0))
			mode = SHOW_SIGNALLED | SHOW_NO_FREE;
		if (mode)
			showjob(out2, thisjob, mode);
		else {
			TRACE(("Not printing status, rootshell=%d, job=%p\n",
				rootshell, job));
			thisjob->changed = 1;
		}
	}

	INTON;
	return pid;
}
Exemplo n.º 5
0
/*
#if	defined HAVE_SELECT
 *
 * Wait for children to send output for us to read.
 *
#else	!HAVE_SELECT
 *
 * Wait up for children to exit.
 *
#endif
 */
void
waitup(void)
{
#if	defined(HAVE_SELECT)
	int count;
	CHILD *pc;
	fd_set *rchildfdsp = NULL;
	int rchildfdsn = 0;
	size_t bytes;

	debugmsg(DM_CALL, "waitup() start\n");

	if (needscan)
		childscan();

	if (activechildren <= 0)
		return;

	/*
	 * Settup which children we want to select() on.
	 */
	for (pc = childlist; pc; pc = pc->c_next)
		if (pc->c_readfd > rchildfdsn)
			rchildfdsn = pc->c_readfd;
	bytes = howmany(rchildfdsn+1, NFDBITS) * sizeof(fd_mask);
	if ((rchildfdsp = (fd_set *)malloc(bytes)) == NULL)
		return;

	memset(rchildfdsp, 0, bytes);
	for (pc = childlist; pc; pc = pc->c_next)
		if (pc->c_readfd > 0) {
			debugmsg(DM_MISC, "waitup() select on %d (%s)\n",
				 pc->c_readfd, pc->c_name);
			FD_SET(pc->c_readfd, rchildfdsp);
		}

	/*
	 * Actually call select()
	 */
	/* XXX remove debugmsg() calls */
	debugmsg(DM_MISC, "waitup() Call select(), activechildren=%d\n", 
		 activechildren);

	count = select(rchildfdsn+1, (SELECT_FD_TYPE *) rchildfdsp, 
		       NULL, NULL, NULL);

	debugmsg(DM_MISC, "waitup() select returned %d activechildren = %d\n", 
		 count, activechildren);

	/*
	 * select() will return count < 0 and errno == EINTR when
	 * there are no active children left.
	 */
	if (count < 0) {
		if (errno != EINTR)
			error("Select failed reading children input: %s", 
			      SYSERR);
		free(rchildfdsp);
		return;
	}

	/*
	 * This should never happen.
	 */
	if (count == 0) {
		error("Select returned an unexpected count of 0.");
		free(rchildfdsp);
		return;
	}

	/*
	 * Go through the list of children and read from each child
	 * which select() detected as ready for reading.
	 */
	for (pc = childlist; pc && count > 0; pc = pc->c_next) {
		/* 
		 * Make sure child still exists 
		 */
		if (pc->c_name && kill(pc->c_pid, 0) < 0 && 
		    errno == ESRCH) {
			debugmsg(DM_MISC, 
				 "waitup() proc %d (%s) died unexpectedly!",
				 pc->c_pid, pc->c_name);
			pc->c_state = PSdead;
			needscan = TRUE;
		}

		if (pc->c_name == NULL ||
		    !FD_ISSET(pc->c_readfd, rchildfdsp))
			continue;

		readchild(pc);
		--count;
	}
	free(rchildfdsp);

#else	/* !defined(HAVE_SELECT) */

	/*
	 * The non-select() version of waitproc()
	 */
	debugmsg(DM_CALL, "waitup() start\n");

	if (waitproc(NULL, TRUE) > 0)
		--activechildren;

#endif	/* defined(HAVE_SELECT) */
	debugmsg(DM_CALL, "waitup() end\n");
}