Sorry for the basic question, but I can't find a straight answer that I can understand on the documentation or with generative AI.
When I do a write
call over a pipe between a parent and child process, will write
only return something != -1 if the data is read by a read
system call?
For instance, take the following code below:
int main(int argc, char* argv[]) {
int workers = 4;
int pfd[2];
int pipe_result = pipe(pfd);
if(pipe_result != 0) {
fail("Can't create pipe");
}
// Parent doesn't need write channel
close(pfd[1]);
for(int i = 0; i < workers; i++) {
pid_t pid = fork();
// Child
if(pid == 0) {
// Child doesn't need read channel
close(pfd[0]);
int count = 101;
// Write count to pipe
int len_sent = write(pfd[1], &count, sizeof(count));
printf("\nChild id: %d Sent %d bytes, count: %d", getpid(), len_sent, count);
// Exit so that the child processes don't loop
close(pfd[1]);
exit(0);
}
else {
int par_count;
// Read
int len = read(pfd[0], &par_count, sizeof(par_count));
printf("\nlen: %d par_count: %d", len, par_count);
}
}
// Close read buffer in parent
close(pfd[0]);
return 0;
}
That code will generally output indicating that 0 or 1 write and read calls were successful. If I move the reads to be after all write calls are done (code below), then everything reports fine.
int main(int argc, char* argv[]) {
int workers = 4;
int pfd[2];
int pipe_result = pipe(pfd);
if(pipe_result != 0) {
fail("Can't create pipe");
}
for(int i = 0; i < workers; i++) {
pid_t pid = fork();
// Child
if(pid == 0) {
// Child doesn't need read channel
close(pfd[0]);
int count = 101;
// Write count to pipe
int len_sent = write(pfd[1], &count, sizeof(count));
printf("\nChild id: %d Sent %d bytes, count: %d", getpid(), len_sent, count);
// Exit so that the child processes don't loop
close(pfd[1]);
exit(0);
}
}
// Parent doesn't need write channel
close(pfd[1]);
// Parent
for(int i = 0; i < workers; i++) {
int par_count;
// Read
int len = read(pfd[0], &par_count, sizeof(par_count));
printf("\nlen: %d par_count: %d", len, par_count);
}
// Close read in parent
close(pfd[0]);
return 0;
}
Why does this change affect the return of the write
calls? I understand why it affects the read
returns - that makes sense to me. But I don't understand why this change makes the write
calls report -1. Is the return of write
dependent on the data being read by a read
call?
To answer the question in the title: No. write()
simply stores the data in the pipe buffer and returns immediately, it doesn't wait for the pipe to be read. When not -1, the return value is the number of bytes that were written to the buffer.
The problem in your code is that you have close(pfd[1])
before the loop that forks all the children. As a result, the children inherit the closed write end of the pipe, so they can't write to it.
You should move that call after the loop.