CONTRIB: tcploop: don't report failed send() or recv()

Many clients close with an RST on the last response or when they get
their response, so let's not report an error.
This commit is contained in:
Willy Tarreau 2016-11-12 18:45:42 +01:00
parent 59623e0aa8
commit 1973e81c06

View File

@ -75,9 +75,11 @@ __attribute__((noreturn)) void die(int code, const char *format, ...)
{ {
va_list args; va_list args;
if (format) {
va_start(args, format); va_start(args, format);
vfprintf(stderr, format, args); vfprintf(stderr, format, args);
va_end(args); va_end(args);
}
exit(code); exit(code);
} }
@ -419,9 +421,10 @@ int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
return -1; return -1;
} }
/* receives N bytes from the socket and returns 0 (or -1 in case of error). /* receives N bytes from the socket and returns 0 (or -1 in case of a recv
* When no arg is passed, receives anything and stops. Otherwise reads the * error, or -2 in case of an argument error). When no arg is passed, receives
* requested amount of data. 0 means read as much as possible. * anything and stops. Otherwise reads the requested amount of data. 0 means
* read as much as possible.
*/ */
int tcp_recv(int sock, const char *arg) int tcp_recv(int sock, const char *arg)
{ {
@ -432,7 +435,7 @@ int tcp_recv(int sock, const char *arg)
count = atoi(arg + 1); count = atoi(arg + 1);
if (count < 0) { if (count < 0) {
fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count); fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
return -1; return -2;
} }
} }
@ -464,10 +467,11 @@ int tcp_recv(int sock, const char *arg)
return 0; return 0;
} }
/* sends N bytes to the socket and returns 0 (or -1 in case of error). If not /* Sends N bytes to the socket and returns 0 (or -1 in case of send error, -2
* set, sends only one block. Sending zero means try to send forever. If the * in case of an argument error. If the byte count is not set, sends only one
* argument starts with ':' then whatever follows is interpreted as the payload * block. Sending zero means try to send forever. If the argument starts with
* to be sent as-is. '\r', '\n', '\t' and '\\' are detected and converted. In * ':' then whatever follows is interpreted as the payload to be sent as-is.
* Escaped characters '\r', '\n', '\t' and '\\' are detected and converted. In
* this case, blocks must be small so that send() doesn't fragment them, as * this case, blocks must be small so that send() doesn't fragment them, as
* they will be put into the trash and expected to be sent at once. * they will be put into the trash and expected to be sent at once.
*/ */
@ -482,7 +486,7 @@ int tcp_send(int sock, const char *arg)
count = atoi(arg + 1); count = atoi(arg + 1);
if (count < 0) { if (count < 0) {
fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count); fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
return -1; return -2;
} }
} }
@ -787,15 +791,23 @@ int main(int argc, char **argv)
case 'R': case 'R':
if (sock < 0) if (sock < 0)
die(1, "Fatal: tcp_recv() on non-socket.\n"); die(1, "Fatal: tcp_recv() on non-socket.\n");
if (tcp_recv(sock, argv[arg]) < 0) ret = tcp_recv(sock, argv[arg]);
if (ret < 0) {
if (ret == -1) // usually ECONNRESET, silently exit
die(0, NULL);
die(1, "Fatal: tcp_recv() failed.\n"); die(1, "Fatal: tcp_recv() failed.\n");
}
break; break;
case 'S': case 'S':
if (sock < 0) if (sock < 0)
die(1, "Fatal: tcp_send() on non-socket.\n"); die(1, "Fatal: tcp_send() on non-socket.\n");
if (tcp_send(sock, argv[arg]) < 0) ret = tcp_send(sock, argv[arg]);
if (ret < 0) {
if (ret == -1) // usually a broken pipe, silently exit
die(0, NULL);
die(1, "Fatal: tcp_send() failed.\n"); die(1, "Fatal: tcp_send() failed.\n");
}
break; break;
case 'E': case 'E':