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().
This commit is contained in:
Willy Tarreau 2013-12-05 00:49:40 +01:00
parent 67ff7e0af3
commit ce3eda7c6a

View File

@ -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)