Mail Archives: cygwin/2001/07/13/20:22:02
Thanks for the diagnosis. Would you be willing to look at the
Cygwin socket code and suggest a fix?
cgf
On Fri, Jul 13, 2001 at 02:14:35PM -0400, Jonathan Kamens wrote:
>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/
--
cgf AT cygnus DOT com Red Hat, Inc.
http://sources.redhat.com/ http://www.redhat.com/
--
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/
- Raw text -