3

I have a program that fork()s a new process and then overwrites that new process's stdin with my file descriptor pipe fd. In this process, I then use execvp() to execute wc and it should read its input from the parent. In the parent, I then write to the write end of the pipe and when done writing, close the pipe.

The problem is that wc is still expecting input and des not exit.
Usually, I can stop wc by typing CTRLD but I can't seem to send that signal in C/C++.

How do I tell wc to stop reading?

EDIT: I did follow the pipe/fork/dup/exec idiom (I think that's what it's called.)
The streaming works with other programs that need input, its just that wc needs the special EOF to stop reading.

int in_fd[2];
//parent-child setup
pipe(in_fd);
child = fork();
if(child == 0) {
    close(in_fd[1]);
    dup2(in_fd[0], 0);
    close(in_fd[0]);
    execvp(cmdArg[0], cmdArg);
} else {
    close(in_fd[0]);
    in_pid = fork_in_proc();
    close(in_fd[1]);
}

//writing function
pid_t fork_in_proc() {
    string line;
    pid_t in_pid;
    if((in_pid = fork()) == 0) {
        close(in_fd[0]);
        ifstream file(stream_file[STREAM_IN].c_str(), ios_base::in);
        if (file.bad()) {
            cerr << "File read error\n";
            return 1;
        }

        while(file.good()) {
            getline(file, line);
            if(file.good()) {
                write(in_fd[1], line.c_str(), line.length());
            }
        }
        int end = 3;
        write(in_fd[1], &end, sizeof(end));
        file.close();
        close(in_fd[1]);
        cout << "PIPE IN" << endl;
        exit(0);
    } else {
        return in_pid;
    }
}

Sorry if the code seems a little disjointed. I had to pull it together from around the file.

Morten Kristensen
  • 7,412
  • 4
  • 32
  • 52
chustar
  • 12,225
  • 24
  • 81
  • 119
  • 1
    CTRL+D doesn't send a signal but makes whatever is reading from the terminal read EOF. – ThiefMaster Nov 22 '11 at 07:18
  • @JoachimPileborg I have added some code. – chustar Nov 22 '11 at 08:01
  • The first thing that jumps out at me is that you are calling `execvp` wrong. The second argument should be an array of strings, with the last entry in the array being `NULL`. – Some programmer dude Nov 22 '11 at 08:10
  • @JoachimPileborg, sorry, I had to simplify it to be able to show it. I do pass an array of strings, I just have this problem when executing `wc` – chustar Nov 22 '11 at 08:12
  • `ios_base::in` means this is not C code - it is C++ code. Ditto notations such as `line.length()`. – Jonathan Leffler Nov 22 '11 at 08:35
  • @chustar Why do you call fork() twice in parent-child setup and fork_in_proc ? If hadn't noted that it works with other executables I would say you swaped the indices 0/1 of in_fd according to http://www.cs.uleth.ca/~holzmann/C/system/pipeforkexec.html – stacker Nov 22 '11 at 09:30
  • In the child process in fork_in_proc there is one code path where you "return 1;" (why not exit()?) without closing in_fd[1]. Are you running into this case? If not, I don't see the error in your code. BTW, you are calling close(in_fd[0]) in the child process in fork_in_proc, but in_fd[0] is already closed there. – Werner Henze Nov 22 '11 at 09:57
  • @stacker I call the fork twice because it is communication between two children that are forked from the same parent and share the same pipes. – chustar Nov 22 '11 at 18:32
  • I entered the following into a c++ file, and it seems to work: https://gist.github.com/805f96e921ec4a4cc51a The only changes I have made apart from includes and main() is to change execvp(...) and istream file(...) to use some constant values. What OS do you use? Are you sure you give execvp the right parameters? (you could try `cat`, instead of `wc` to see what's going on.) – DirtY iCE Nov 22 '11 at 23:16

1 Answers1

0

wc exits when you close the stdout.

Mp0int
  • 18,172
  • 15
  • 83
  • 114
jimmy
  • 112
  • 1
  • 2