Beispiel #1
0
/* state change of children handled here */
static void sigchld_handler(int sig)
{
	pid_t child_pid;
	jobs **job;
	int status;

	/*
	 * There can be multiple SIGCHLD at once, not necessarily they will all be handled,
	 * so we reap all the children in non-blocking mode that takes care of the pending child
	 * whose SIGCHLD is not attended
	 */

	/* SIGCHLD should be blocked in critical section of modifying joblist */
	/* thy shall NOT pass */
	while ((child_pid = waitpid(-1, &status, WNOHANG|WUNTRACED|WCONTINUED)) > 0) {
		if (WIFEXITED(status)) {
			deljob(child_pid);
		}

		else if (WIFSIGNALED(status)) {
			job = getjob(child_pid, 0);
			if (NOTNULL(job)) {
				shell_printf(SHELLPRINT_CHKSS | SHELLPRINT_CHKTERM,
						TERMSTR_GREEN("SIGCHLD: ")"[%d] (%d) killed by signal %d\n",
						(*job)->jid, (*job)->pid[0], WTERMSIG(status));
				deljob(child_pid);
			}
		}

		else if (WIFSTOPPED(status)) {
			job = getjob(child_pid, 0);
			if (NOTNULL(job)) {
				(*job)->state = ST;
				shell_printf(SHELLPRINT_CHKSS | SHELLPRINT_CHKTERM,
						TERMSTR_GREEN("SIGCHLD : ")"[%d] (%d) stopped by signal %d\n",
						(*job)->jid, (*job)->pid[0], WSTOPSIG(status));
			}
		}

		else if (WIFCONTINUED(status)) {
			job = getjob(child_pid, 0);
			if (NOTNULL(job))
				(*job)->state = BG;
		}
	}
	/* thy shall pass */
}
Beispiel #2
0
/*
 * the basic wait for foreground used by fg cmd and basic
 * non bg cmd in the shell. Make sure SIGCHLD is blocked
 * to avoid race conditions that make the joblist unreliable.
 * No terminal control or printing if subshell
 * */
void wait_fg(jobs **job)
{
	int status, i;

	/* thy shall NOT pass */

	for (i=0; NOTNULL(job); i++) {
		if (!subshell_flag && tcsetpgrp(TERMFD, (*job)->pid[0]) < 0)
			perror("tcsetpgrp");
		while (waitpid((*job)->pid[i], &status, WUNTRACED) == 0)
			;

		if (WIFEXITED(status)) {
			if (!subshell_flag && tcsetpgrp(TERMFD, getpid()) < 0)
				perror("tcsetpgrp");
			if ((*job)->pid[i+1] == 0) {
				deljob((*job)->pid[0]);
				break;
			}
		}

		else if (WIFSIGNALED(status)) {
			if (!subshell_flag && tcsetpgrp(TERMFD, getpid()) < 0)
				perror("tcsetpgrp");
			shell_printf(SHELLPRINT_CHKSS | SHELLPRINT_CHKTERM,
					"[%d] (%d) killed by signal %d\n", (*job)->jid, (*job)->pid[0],
					WTERMSIG(status));
			deljob((*job)->pid[0]);
			break;
		}

		else if (WIFSTOPPED(status)) {
			if (!subshell_flag && tcsetpgrp(TERMFD, getpid()) < 0)
				perror("tcsetpgrp");
			shell_printf(SHELLPRINT_CHKSS | SHELLPRINT_CHKTERM,
					"[%d] (%d) stopped by signal %d\n", (*job)->jid,
					(*job)->pid[0], WSTOPSIG(status));
			(*job)->state = ST;
			break;
		}
	}
	/* thy shall pass */
}
Beispiel #3
0
STATIC void
freejob(struct job *jp)
{
	struct procstat *ps;
	int i;

	INTOFF;
	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
		if (ps->cmd != nullstr)
			ckfree(ps->cmd);
	}
	if (jp->ps != &jp->ps0)
		ckfree(jp->ps);
	jp->used = 0;
#if JOBS
	deljob(jp);
#endif
	INTON;
}