How to wait child process termination?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello.

I'm trying to create a minimum shell that has almost
no built-in functions for my kernel patch's demonstration use.
It doesn't need to handle job controls, redirections etc.
Just fork(2) and execvp(3) and wait(2) until the execvp'ed
process terminates.

The following is a part of the shell program,
but the wait(2) returns before some program terminates.
For example,
(1) invoke /bin/tcsh from this shell
(2) invoke /bin/ls from tcsh
(3) exit from tcsh
returns to this shell after tcsh(1) process terminates, but
(1) invoke /bin/tcsh from this shell
(2) invoke /usr/bin/less from tcsh
returns to this shell before less(1) process terminates.
I don't want to return to this shell before execvp'ed process terminates.
Please tell me how to wait(2).

I don't want to use system(3) nor popen(3), for they needs /bin/sh
for internal processing.

I think I need to handle some signal,
but I can't find an appropriate simple source code.
Handling only SIGINT SIGQUIT and SIGCHLD are enough?

Regards...

-----
  Tetsuo Handa

<-- portion of the shell -->

static char *args[MAX_ARGS];
static int Shell(void) {
	int status, err;
	pid_t pid;
	struct sigaction sa, intr, quit;
	sigset_t omask;
	sa.sa_handler = SIG_IGN;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGINT, &sa, &intr) < 0) goto out;
	if (sigaction(SIGQUIT, &sa, &quit) < 0) goto out_restore_sigint;
	sigaddset(&sa.sa_mask, SIGCHLD);
	if (sigprocmask(SIG_BLOCK, &sa.sa_mask, &omask) == EOF) {
		sigaction(SIGQUIT, &quit, (struct sigaction *) NULL);
	out_restore_sigint:
		sigaction(SIGINT, &intr, (struct sigaction *) NULL);
	out:
		return -1;
	}
	switch (pid = fork()) {
	case 0:
		sigaction(SIGINT, &intr, (struct sigaction *) NULL);
		sigaction(SIGQUIT, &quit, (struct sigaction *) NULL);
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL);
		execvp(args[0], args);
		err = errno;
		fprintf(stderr, "ERROR: Can't execute. %s : %s\n", args[0], strerror(err));
		_exit(127);
		break;
	case -1:
		err = errno;
		fprintf(stderr, "ERROR: Can't fork. : %s\n", strerror(err));
		status = -1;
		break;
	default:
		while ((err = waitpid(pid, &status, 0)) == EOF && errno == EINTR);
		if (err != pid) status = -1;
	}
	sigaction(SIGINT, &intr, (struct sigaction *) NULL);
	sigaction(SIGQUIT, &quit, (struct sigaction *) NULL);
	sigprocmask(SIG_SETMASK, &omask, (sigset_t *) NULL);
	return status;
}

--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux