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");
}