On Linux, why does this print 0
and hang rather than printing 0 up to 999?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
int n = 1000;
int fromparent[2];
int fromchild[2];
int *x = 0;
pipe(fromparent);
pipe(fromchild);
if (fork() == 0) {
/* child */
while (1) {
read(fromparent[0], x, 1);
write(fromchild[1], x, 1);
}
} else {
/* parent */
for (int i = 0; i < n; i ) {
printf("%d\n", i);
write(fromparent[1], x, 1);
read(fromchild[0], x, 1);
}
exit(0);
}
}
CodePudding user response:
The problem is simple: you pass a null pointer to read
and write
.
Change the definition of x
from int *x = 0;
to:
char x[1] = { 0 };
As posted, the behavior is somewhat counterintuitive:
passing a null pointer to
write
causes it to return-1
immediately, settingerrno
toEINVAL
.conversely, passing a null pointer to
read
causes it to wait for input and only return-1
and seterrno
toEINVAL
once input is available. This is causing both processes to block on theread
calls.
Here is a simple test to illustrate this behavior:
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int n;
errno = 0;
n = read(0, NULL, 1);
printf("n=%d, errno=%d\n", n, errno);
return 0;
}
This program waits for input if run from the console and prints n=-1, errno=14
after the user hits enter.
Conversely, it prints n=0, errno=0
when standard input is redirected from /dev/null
.