This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
The test program below creates a socketpair and then forks. The child writes some data to the socketpair and then exits, and the parent tries to read that data. Instead of printing "PARENT: foo (exiting)" as it should, the parent prints "PARENT: read: Connection reset by peer". This is also true if you compile the program with "-DUSE_CLOSE" to tell the child to close the write end of the socketpair before exiting. However, it works properly if you compile the program with "-DUSE_SHUTDOWN" to tell the child to shutdown its end of the socketpair before exiting. There are two different bugs here: 1) close() on an end of a socketpair should behave the same as shutdown(..., 2), in terms of flushing data to the other end of the socketpair. 2) Data sent by the writer should be flushed to the reader, not lost, when the writer exits. This problem causes recent versions of rsync, when they are compiled to use socketpairs (which is the default), to report a bogus "read error: connection reset by peer" at the end of every rsync, even when it in fact copied everything successfully. I'm going to submit a patch to the rsync maintainers suggesting that they work around this problem by calling shutdown() before exiting. jik ************************* #include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <signal.h> #include <sys/socket.h> main() { int pipefds[2]; int readfd, writefd; char inbuf[4]; char outbuf[4] = "foo"; int pid; fd_set readfds, exceptfds; socketpair(AF_UNIX, SOCK_STREAM, 0, pipefds); /* pipe(pipefds); */ readfd = pipefds[0]; writefd = pipefds[1]; if (pid = fork()) { fprintf(stderr, "PARENT: close(writefd)\n"); close(writefd); FD_ZERO(&readfds); FD_SET(readfd, &readfds); exceptfds = readfds; fprintf(stderr, "PARENT: selecting\n"); if (select(readfd + 1, &readfds, NULL, &exceptfds, NULL) <= 0) { perror("PARENT: select"); exit(1); } if (FD_ISSET(readfd, &exceptfds)) { fprintf(stderr, "PARENT: exception is set\n"); } if (FD_ISSET(readfd, &readfds)) { fprintf(stderr, "PARENT: read is set\n"); } fprintf(stderr, "PARENT: reading\n"); if (read(readfd, inbuf, sizeof(inbuf)) != sizeof(inbuf)) { perror("PARENT: read"); exit(1); } printf("PARENT: %s (exiting)\n", inbuf); exit(0); } else { fprintf(stderr, "CHILD: close(readfd)\n"); close(readfd); fprintf(stderr, "CHILD: writing\n"); if (write(writefd, outbuf, sizeof(outbuf)) != sizeof(outbuf)) { perror("CHILD: write"); exit(1); } #ifdef USE_SHUTDOWN shutdown(writefd, 2); #endif #ifdef USE_CLOSE close(writefd); #endif fprintf(stderr, "CHILD: exiting\n"); exit(0); } } -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |