From: Willy Tarreau Date: Wed, 4 Dec 2013 23:49:40 +0000 (+0100) Subject: MINOR: connection: clear errno prior to checking for errors X-Git-Tag: v1.5-dev20~162 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce3eda7c6a8e594cf690b3c2f8e35378e8601dfc;p=thirdparty%2Fhaproxy.git MINOR: connection: clear errno prior to checking for errors At some places, we report an error by just detecting FD_POLL_ERR. The problem is that the caller never knows if it must use errno or call getsockopt(SO_ERROR). And since this last one clears the pending error from the queue, it cannot be used inconditionally. An elegant solution consists in clearing errno prior to inspecting FD_POLL_ERR. The caller then knows that if it gets CO_FL_ERROR and errno == 0, it must call getsockopt(). --- diff --git a/src/raw_sock.c b/src/raw_sock.c index ec76604397..43cd70a830 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -74,6 +74,8 @@ int raw_sock_to_pipe(struct connection *conn, struct pipe *pipe, unsigned int co int ret; int retval = 0; + errno = 0; + /* Under Linux, if FD_POLL_HUP is set, we have reached the end. * Since older splice() implementations were buggy and returned * EAGAIN on end of read, let's bypass the call to splice() now. @@ -86,6 +88,7 @@ int raw_sock_to_pipe(struct connection *conn, struct pipe *pipe, unsigned int co /* report error on POLL_ERR before connection establishment */ if ((fdtab[conn->t.sock.fd].ev & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) { conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH; + errno = 0; /* let the caller do a getsockopt() if it wants it */ return retval; } } @@ -223,12 +226,16 @@ int raw_sock_from_pipe(struct connection *conn, struct pipe *pipe) * empty). The caller is responsible for taking care of those events and * avoiding the call if inappropriate. The function does not call the * connection's polling update function, so the caller is responsible for this. + * errno is cleared before starting so that the caller knows that if it spots an + * error without errno, it's pending and can be retrieved via getsockopt(SO_ERROR). */ static int raw_sock_to_buf(struct connection *conn, struct buffer *buf, int count) { int ret, done = 0; int try = count; + errno = 0; + if (unlikely(!(fdtab[conn->t.sock.fd].ev & FD_POLL_IN))) { /* stop here if we reached the end of data */ if ((fdtab[conn->t.sock.fd].ev & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)