I'm implementing my own tiny shell. Both ls | cat
and ls | more
work well if I don't create a new group for these two child processes.
However, after I create a new process group for these two processes (the first one ls
process is the leader process) by simply calling setpgid
in the parent process. ls | cat
always works but ls | more
hangs.
It looks like one of my process is getting stuck at the dup2
system call. Is there any other things I need to consider? What happens if ls
terminates first before I call setpgid
for more
process? Do I need to block ls
process not to call execve
until setpgid
is done for more
process?
EDIT:
My code:
Sometimes it gets stuck. But when I tried to add printf
to locate the position, it's finished successfully. No error arises.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define CHECK(syscall, msg) do { \
if ((syscall) == -1) { \
perror(msg); \
exit(1); \
} \
} while(0)
#define SAFE_CLOSE_NOT_STD(fd) do { \
if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != -1) { \
CHECK(close(fd), "close error"); \
fd = -1; \
} \
} while(0)
int main () {
int ls_pid, more_pid;
int pipefd[2];
char *ls_argv[] = { "/bin/ls", NULL };
char *more_argv[] = { "/usr/bin/more", NULL };
CHECK(pipe(pipefd), "pipe error");
CHECK(ls_pid = fork(), "fork error");
if (!ls_pid) {
CHECK(dup2(pipefd[1], STDOUT_FILENO), "dup2 error");
CHECK(close(pipefd[1]), "close error");
CHECK(execvp(ls_argv[0], ls_argv), "execvp error");
} else {
SAFE_CLOSE_NOT_STD(pipefd[1]);
}
setpgid(ls_pid, ls_pid);
CHECK(more_pid = fork(), "fork error");
if (!more_pid) {
CHECK(dup2(pipefd[0], STDIN_FILENO), "dup2 error");
CHECK(close(pipefd[0]), "close error");
CHECK(execvp(more_argv[0], more_argv), "execvp error");
} else {
SAFE_CLOSE_NOT_STD(pipefd[0]);
}
setpgid(more_pid, ls_pid); // it works if I remove this line
CHECK(wait(NULL), "wait error");
CHECK(wait(NULL), "wait error");
printf("Finish\n");
}