diff options
author | pjd <pjd@FreeBSD.org> | 2011-04-02 09:29:53 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2011-04-02 09:29:53 +0000 |
commit | ee9b74620b4b94a6bf4a1fe552711dc4e1622c8d (patch) | |
tree | d6e4e84f8ebc70f7c3dc951c8a07f25b58b066d9 /sbin | |
parent | 52d273ec9959ccf9598a661f0a5a837ee5579642 (diff) | |
download | FreeBSD-src-ee9b74620b4b94a6bf4a1fe552711dc4e1622c8d.zip FreeBSD-src-ee9b74620b4b94a6bf4a1fe552711dc4e1622c8d.tar.gz |
When we are operating on blocking socket and get EAGAIN on send(2) or recv(2)
this means that request timed out. Translate the meaningless EAGAIN to
ETIMEDOUT to give administrator a hint that he might need to increase timeout
in configuration file.
MFC after: 1 month
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/hastd/proto_common.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c index 91d2435..1d4c606 100644 --- a/sbin/hastd/proto_common.c +++ b/sbin/hastd/proto_common.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation + * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> * All rights reserved. * * This software was developed by Pawel Jakub Dawidek under sponsorship from @@ -34,8 +35,11 @@ __FBSDID("$FreeBSD$"); #include <sys/socket.h> #include <errno.h> +#include <fcntl.h> +#include <stdbool.h> #include <stdlib.h> #include <strings.h> +#include <unistd.h> #include "pjdlog.h" #include "proto_impl.h" @@ -45,6 +49,16 @@ __FBSDID("$FreeBSD$"); #define MAX_SEND_SIZE 32768 #endif +static bool +blocking_socket(int sock) +{ + int flags; + + flags = fcntl(sock, F_GETFL); + PJDLOG_ASSERT(flags >= 0); + return ((flags & O_NONBLOCK) == 0); +} + static int proto_descriptor_send(int sock, int fd) { @@ -99,11 +113,19 @@ proto_common_send(int sock, const unsigned char *data, size_t size, int fd) do { sendsize = size < MAX_SEND_SIZE ? size : MAX_SEND_SIZE; done = send(sock, data, sendsize, MSG_NOSIGNAL); - if (done == 0) + if (done == 0) { return (ENOTCONN); - else if (done < 0) { + } else if (done < 0) { if (errno == EINTR) continue; + /* + * If this is blocking socket and we got EAGAIN, this + * means the request timed out. Translate errno to + * ETIMEDOUT, to give administrator a hint to + * eventually increase timeout. + */ + if (errno == EAGAIN && blocking_socket(sock)) + errno = ETIMEDOUT; return (errno); } data += done; @@ -169,10 +191,19 @@ proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp) do { done = recv(sock, data, size, MSG_WAITALL); } while (done == -1 && errno == EINTR); - if (done == 0) + if (done == 0) { return (ENOTCONN); - else if (done < 0) + } else if (done < 0) { + /* + * If this is blocking socket and we got EAGAIN, this + * means the request timed out. Translate errno to + * ETIMEDOUT, to give administrator a hint to + * eventually increase timeout. + */ + if (errno == EAGAIN && blocking_socket(sock)) + errno = ETIMEDOUT; return (errno); + } if (fdp == NULL) return (0); return (proto_descriptor_recv(sock, fdp)); |