I'm tying to make a simple shell, but I'm stuck implementing pipes. Here's the part of my code that pertains to the pipe. There's more I can put if you think it'll help, but the rest of it works exactly as expected.
args[i] = NULL;
p_flag = 1;
int stop = i;
// we have to fork again so we can write to a buffer file.
// First we creat the pipe.
if (pipe(p_file) == -1) {
//check if the pipe failed
fprintf(stderr, "There was an error creating the pipe\n");
}
switch (pid = fork()) {
case 0:
//Open up the input end of the pipe for writing.
printf("test1\n");
close(p_file[0]);
printf("test2\n");
dup2(p_file[1], 1);
printf("test3\n");
execvp(args[0], args);
fprintf(stderr, "ERROR %s no such program.\n", line);
exit(1);
break;
case -1:
fprintf(stderr, "ERROR can't create child process!\n");
break;
default:
wait();
break;
}
/*
at this point only the first child should still be running
and since we waited we know that the buffer file has our input.
Now we have to redirect our input to read from the buffer and
run the rest of the commands normally. first the args array has
to be cleaned up we want the commands past the pipe symbol to be
in front.
*/
int j = 0;
stop++;
while (args[stop] != NULL) {
args[j] = args[stop];
j++;
stop++;
}
args[j] = NULL;
close(p_file[1]);
dup2(p_file[0], 0);
As you can see, I've put in some print statements to try and figure out where exactly it was getting stuck, and I get test1
and test2
output before the program sits processing forever spinning its wheels. I have to ctrl+c to get the prompt back. I don't know why it's stuck doing the dup2
command. The only important thing left out of this code snippet is initialization of p_file
and it's an array of size two (i.e. int p_file[2];
).
You have a serious misconception. Pipes are an inter-process communication mechanism. The processes communicating via a pipe generally run concurrently, not sequentially. They must run concurrently in a general-purpose implementation, such as one provided by a shell, because each pipe has only a finite buffer, and writes to it will block or fail when the buffer fills. Unless you can be certain that the writer(s) will not fill the pipe's buffer before exiting, the reader(s) must be ready and waiting to consume data from the read end of the pipe before the you can expect the writer(s) to finish.
It is therefore wrong to
wait()
for the first process before starting the second, and this could be why your program hangs. Instead, the shell must start a child process for each end of the pipe, and then wait for both.Additionally, as I wrote in comments, you call
wait()
without the proper arguments. This produces undefined behavior, which could itself be an indefinite wait, but which might also be almost anything else.As for your debugging output, @Ctx explained in his own comment why you do not see everything you expected. I do not, however, see any reason to doubt your claim that the program hangs until you interrupt it.