Well, putting together a stripped down example of a parent process passing data to my program lead me to the problem/solution.
For completeness, here's the other program:
Code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
int readParent[2];
int writeParent[2];
pipe(readParent);
pipe(writeParent);
pid_t pid = fork();
if (pid == 0) {
// This is the child
close(writeParent[1]); // <-- Without this, the program blocks for more input
dup2(writeParent[0],0);
close(readParent[0]);
dup2(readParent[1],1);
execl("test", "test", NULL);
} else {
// This is the parent
FILE *in = fdopen(readParent[0], "r");
FILE *out = fdopen(writeParent[1], "w");
double nums[] = {1, 2, 3};
int i;
for (i = 0; i < 3; i++)
fprintf(out, "%lf ", nums[i]);
fclose(out);
double d;
int n = fscanf(in, "%lf", &d);
if (n < 1) {
printf("Something is broken\n");
exit(EXIT_FAILURE);
}
printf("Parent recieved: %lf\n", d);
}
exit(EXIT_SUCCESS);
}
This works as intended. What I didn't have before were the lines closing the other end of the pipes in the child. In particular, without the statement close(writeParent[1]), the first program will block, waiting for more input after the last item has been sent.
Here's my understanding - let me know if I got this right. The pipe writeParent[] has a read end (0) and a write end (1). When I call fork(), both the parent and child process have their own handle (file descriptor) to both ends of the pipe. While the parent closed their write end, the client still had theirs open. Thus, EOF was not hit since the pipe was still open. Is that about right?
So the problem was in my calling program, and I misdiagnosed it as being related to how I was having to send EOF twice from the command line.