1

I'm using the following code part to perform input redirection for my custom C++ shell. While the output redirection similar to this works well, the child process for the input redirection stays open and doesn't return, like it keeps waiting for new input. What is the best way to 'ask' or 'force' a child process like this to return immediately after reading input?

Code for input redirection

int in_file = open(in, O_CREAT | O_RDONLY , S_IREAD | S_IWRITE);
pid_t pid = fork();
    if (!pid) {
         dup2(in_file, STDIN_FILENO);
         if (execvp(argv[0], argv) < 0) {
             cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
             exit(EXIT_FAILURE);
         }
     }
close(in_file);

Code for output redirection

out_file = open(out, O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
pid_t pid = fork();
    if (!pid) {
         dup2(out_file, STDOUT_FILENO);
         if (execvp(argv[0], argv) < 0) {
             cerr << "*** ERROR: exec failed: "<< argv[0] << endl;
             exit(EXIT_FAILURE);
          }
    }    
close(out_file);

I used the following commands to test:

ps aux > out.txt
grep root < out.txt

The first command returns to shell after succesfully writing to out.txt. The second command reads succesfully from out.txt, but doesn't return or stop.

Cloud
  • 458
  • 1
  • 13
  • 34

2 Answers2

0

First, check the arguments to execvp(). If this code is part of main(int argc, char* argv[]), then argv[0] is your own program, not grep. This means that your program is recursively re-executing itself for ever.

Then, make sure that there is no error when opening in with:

if (in_file < 0) { perror(in); ... }

If in_file is an invalid descriptor, dup2() will fail and grep will run reading from the terminal, hence, not terminating. BTW, using O_CREAT | O_RDONLY looks fishy. Why read from a file that does not previously exist?

jop
  • 2,226
  • 15
  • 16
0

The child still has the in_file open. You must close it before exec:

dup2(in_file, STDIN_FILENO);
close(in_file);

(error checking omitted for brevity). Because the child still has an open file descriptor, it never sees the file as being closed, so it blocks on a read waiting for someone to write more data. The child process does not realize that it is the one holding the file descriptor open. Another option is to set the 'close-on-exec' flag for the file descriptor, so that it is closed automatically on exec. (Search for FD_CLOEXEC)

Community
  • 1
  • 1
William Pursell
  • 204,365
  • 48
  • 270
  • 300