diff --git a/CHANGES b/CHANGES index 535fa13..c913700 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,10 @@ Corrections: Test: IP_SENDTO_6 Thanks to Sören for sending an initial patch. + Under certain circumstances, Socat printed the "socket ... is at EOF" + multiple times. + Test: MULTIPLE_EOF + ####################### V 1.7.3.3: Corrections: diff --git a/socat.c b/socat.c index 0ec611e..d65eb65 100644 --- a/socat.c +++ b/socat.c @@ -1076,10 +1076,10 @@ int _socat(void) { XIO_RDSTREAM(sock1)->fd); /*! */ mayrd1 = true; polling = 1; /* do not hook this eof fd to poll for pollintv*/ - } else { + } else if (XIO_RDSTREAM(sock1)->eof <= 2) { Notice1("socket 1 (fd %d) is at EOF", XIO_GETRDFD(sock1)); xioshutdown(sock2, SHUT_WR); - XIO_RDSTREAM(sock1)->eof = 2; + XIO_RDSTREAM(sock1)->eof = 3; XIO_RDSTREAM(sock1)->ignoreeof = false; } } else if (polling && XIO_RDSTREAM(sock1)->ignoreeof) { @@ -1099,10 +1099,10 @@ int _socat(void) { XIO_RDSTREAM(sock2)->fd); mayrd2 = true; polling = 1; /* do not hook this eof fd to poll for pollintv*/ - } else { + } else if (XIO_RDSTREAM(sock2)->eof <= 2) { Notice1("socket 2 (fd %d) is at EOF", XIO_GETRDFD(sock2)); xioshutdown(sock1, SHUT_WR); - XIO_RDSTREAM(sock2)->eof = 2; + XIO_RDSTREAM(sock2)->eof = 3; XIO_RDSTREAM(sock2)->ignoreeof = false; } } else if (polling && XIO_RDSTREAM(sock2)->ignoreeof) { diff --git a/test.sh b/test.sh index 2602f63..4fa2af9 100755 --- a/test.sh +++ b/test.sh @@ -13094,6 +13094,45 @@ esac N=$((N+1)) +# test if the multiple EOF messages are fixed +NAME=MULTIPLE_EOF +case "$TESTS" in +*%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) +TEST="$NAME: multiple EOF messages" +# start two processes, connected via UNIX socket. The listener gets EOF from local address immediately; the second process then sends data. If the listener reports "socket 1 (fd .*) is at EOF" only once, the test succeeded +if ! eval $NUMCOND; then :; else +ts="$td/test$N.sock" +tf="$td/test$N.stdout" +te="$td/test$N.stderr" +tdiff="$td/test$N.diff" +da="test$N $(date) $RANDOM" +CMD0="$TRACE $SOCAT $opts -d -d UNIX-LISTEN:$ts /dev/null" +CMD1="$TRACE $SOCAT $opts -d -d - UNIX-CONNECT:$ts" +printf "test $F_n $TEST... " $N +$CMD0 >/dev/null 2>"${te}0" & +pid0=$! +waitunixport $ts 1 +echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" +rc1=$? +kill $pid0 2>/dev/null; wait +if [ $(grep "socket 2 (fd .*) is at EOF" ${te}0 |wc -l) -eq 1 ]; then + $PRINTF "$OK\n" + numOK=$((numOK+1)) +else + $PRINTF "$FAILED\n" + echo "$CMD0 &" + echo "$CMD1" + cat "${te}0" + cat "${te}1" + numFAIL=$((numFAIL+1)) + listFAIL="$listFAIL $N" +fi +fi # NUMCOND + ;; +esac +N=$((N+1)) + + ################################################################################## #================================================================================= # here come tests that might affect your systems integrity. Put normal tests diff --git a/xio.h b/xio.h index 9399a60..0b917d8 100644 --- a/xio.h +++ b/xio.h @@ -129,7 +129,8 @@ typedef struct single { bool ignoreeof; /* option ignoreeof; do not pass eof condition to app*/ int eof; /* 1..exec'd child has died, but no explicit eof occurred - 2..fd0 has reached EOF (definitely; never with + 2..fd0 has reached EOF, but check for ignoreeof + 3..fd0 has reached EOF (definitely; never with ignoreeof! */ size_t wsize; /* write always this size; 0..all available */ size_t readbytes; /* read only so many bytes; 0...unlimited */