ECONNRESET,EPIPE on read() and shutdown() are now errors

This commit is contained in:
Gerhard Rieger 2023-06-18 15:58:24 +02:00
parent 1861303728
commit fe4444a70b
4 changed files with 37 additions and 16 deletions

12
CHANGES
View file

@ -67,6 +67,18 @@ Corrections:
Better formatted help output; address keywords in help output are now Better formatted help output; address keywords in help output are now
printed in uppercase. printed in uppercase.
In previous Socat versions errors EPIPE and ECONNRESET on read() were
handled at warning level, thus not automatically leading to termination
with exit code 1. Beginning with this release these conditions are
handled as errors with termination and exit code 1 to not pretend
success on possible data loss.
Problem reported by Scott Burkett.
In previous Socat versions errors on shutdown() were ignored (info
level).
Now Socat handles EPIPE and ECONNRESET as error to indicate possible
failure of data transfer.
Coding: Coding:
Introduced groups_t instead of uint32_t, for more flexibility. Introduced groups_t instead of uint32_t, for more flexibility.

View file

@ -789,8 +789,7 @@ label(ADDRESS_SCTP_LISTEN)dit(bf(tt(SCTP-LISTEN:<port>)))
link(sctp-nodelay)(OPTION_SCTP_NODELAY), link(sctp-nodelay)(OPTION_SCTP_NODELAY),
link(su)(OPTION_SUBSTUSER), link(su)(OPTION_SUBSTUSER),
link(reuseaddr)(OPTION_REUSEADDR), link(reuseaddr)(OPTION_REUSEADDR),
link(retry)(OPTION_RETRY), link(retry)(OPTION_RETRY)nl()
link(cool-write)(OPTION_COOL_WRITE)nl()
See also: See also:
link(SCTP4-LISTEN)(ADDRESS_SCTP4_LISTEN), link(SCTP4-LISTEN)(ADDRESS_SCTP4_LISTEN),
link(SCTP6-LISTEN)(ADDRESS_SCTP6_LISTEN), link(SCTP6-LISTEN)(ADDRESS_SCTP6_LISTEN),
@ -1415,8 +1414,7 @@ label(ADDRESS_VSOCK_LISTEN)dit(bf(tt(VSOCK-LISTEN:<port>)))
link(backlog)(OPTION_BACKLOG), link(backlog)(OPTION_BACKLOG),
link(su)(OPTION_SUBSTUSER), link(su)(OPTION_SUBSTUSER),
link(reuseaddr)(OPTION_REUSEADDR), link(reuseaddr)(OPTION_REUSEADDR),
link(retry)(OPTION_RETRY), link(retry)(OPTION_RETRY)nl()
link(cool-write)(OPTION_COOL_WRITE)nl()
See also: See also:
link(VSOCK-CONNECT)(ADDRESS_VSOCK_CONNECT) link(VSOCK-CONNECT)(ADDRESS_VSOCK_CONNECT)
@ -1626,9 +1624,10 @@ label(OPTION_COOL_WRITE)dit(bf(tt(cool-write[=<bool>])))
Takes it easy when write fails with EPIPE or ECONNRESET and logs the message Takes it easy when write fails with EPIPE or ECONNRESET and logs the message
with em(notice) level instead of em(error). with em(notice) level instead of em(error).
This prevents the log file from being filled with useless error messages This prevents the log file from being filled with useless error messages
when socat is used as a high volume server or proxy where clients often when socat() is used as a high volume server or proxy where clients often
abort the connection.nl() abort the connection. Use this option only with option
This option is experimental. link(fork)(OPTION_FORK) because otherwise it might cause socat() to exit
with code 0 even on failure.nl()
label(OPTION_END_CLOSE)dit(bf(tt(end-close[=<bool>]))) label(OPTION_END_CLOSE)dit(bf(tt(end-close[=<bool>])))
Changes the (address dependent) method of ending a connection to just close Changes the (address dependent) method of ending a connection to just close
the file descriptors. This is useful when the connection is to be reused by the file descriptors. This is useful when the connection is to be reused by

View file

@ -59,12 +59,9 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
if (bytes < 0) { if (bytes < 0) {
_errno = errno; _errno = errno;
switch (_errno) { switch (_errno) {
#if 1 case EPIPE:
case EPIPE: case ECONNRESET: case ECONNRESET:
Warn4("read(%d, %p, "F_Zu"): %s", /*PASSTHROUGH*/
pipe->fd, buff, bufsiz, strerror(_errno));
break;
#endif
default: default:
Error4("read(%d, %p, "F_Zu"): %s", Error4("read(%d, %p, "F_Zu"): %s",
pipe->fd, buff, bufsiz, strerror(_errno)); pipe->fd, buff, bufsiz, strerror(_errno));

View file

@ -52,9 +52,22 @@ int xioshutdown(xiofile_t *sock, int how) {
} }
return 0; return 0;
case XIOSHUT_DOWN: case XIOSHUT_DOWN:
if ((result = Shutdown(sock->stream.fd, how)) < 0) { result = Shutdown(sock->stream.fd, how);
Info3("shutdown(%d, %d): %s", if (result < 0) {
sock->stream.fd, how, strerror(errno)); int level, _errno = errno;
switch (_errno) {
case EPIPE:
case ECONNRESET:
level = E_ERROR;
break;
default:
level = E_INFO; /* old behaviour */
break;
}
Msg3(level, "shutdown(%d, %d): %s",
sock->stream.fd, how, strerror(_errno));
errno = _errno;
return -1;
} }
return 0; return 0;
#if _WITH_SOCKET #if _WITH_SOCKET