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);
}
}
>Solution :
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
writecauses it to return-1immediately, settingerrnotoEINVAL. -
conversely, passing a null pointer to
readcauses it to wait for input and only return-1and seterrnotoEINVALonce input is available. This is causing both processes to block on thereadcalls.
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.