MINOR: tevt/connection: Add support for POLL_HUP/POLL_ERR events
Connection errors can be detected via connect/recv/send syscall, but also because it was reported by the poller. So dedicated events, at the FD level, are introduced to make the difference. term_events tool was updated accordingly.
This commit is contained in:
parent
c7457427ab
commit
71320fc9c1
@ -25,7 +25,7 @@ static const char *tevt_unknown_types[16] = {
|
|||||||
static const char *tevt_fd_types[16] = {
|
static const char *tevt_fd_types[16] = {
|
||||||
[ 0] = "-", [ 1] = "shutw", [ 2] = "shutr", [ 3] = "rcv_err",
|
[ 0] = "-", [ 1] = "shutw", [ 2] = "shutr", [ 3] = "rcv_err",
|
||||||
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "conn_err",
|
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "conn_err",
|
||||||
[ 8] = "intercepted", [ 9] = "-", [10] = "-", [11] = "-",
|
[ 8] = "intercepted", [ 9] = "conn_poll_err", [10] = "poll_err", [11] = "poll_hup",
|
||||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -763,6 +763,10 @@ enum fd_term_event_type {
|
|||||||
/* unused: 5, 6 */
|
/* unused: 5, 6 */
|
||||||
fd_tevt_type_connect_err = 7,
|
fd_tevt_type_connect_err = 7,
|
||||||
fd_tevt_type_intercepted = 8,
|
fd_tevt_type_intercepted = 8,
|
||||||
|
|
||||||
|
fd_tevt_type_connect_poll_err = 9,
|
||||||
|
fd_tevt_type_poll_err = 10,
|
||||||
|
fd_tevt_type_poll_hup = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hs_term_event_type {
|
enum hs_term_event_type {
|
||||||
|
@ -72,12 +72,14 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe,
|
|||||||
*/
|
*/
|
||||||
if (unlikely(!(fdtab[conn->handle.fd].state & FD_POLL_IN))) {
|
if (unlikely(!(fdtab[conn->handle.fd].state & FD_POLL_IN))) {
|
||||||
/* stop here if we reached the end of data */
|
/* stop here if we reached the end of data */
|
||||||
if ((fdtab[conn->handle.fd].state & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
|
if ((fdtab[conn->handle.fd].state & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_hup);
|
||||||
goto out_read0;
|
goto out_read0;
|
||||||
|
}
|
||||||
|
|
||||||
/* report error on POLL_ERR before connection establishment */
|
/* report error on POLL_ERR before connection establishment */
|
||||||
if ((fdtab[conn->handle.fd].state & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
|
if ((fdtab[conn->handle.fd].state & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_rcv_err);
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_err);
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
||||||
conn_set_errcode(conn, CO_ER_POLLERR);
|
conn_set_errcode(conn, CO_ER_POLLERR);
|
||||||
errno = 0; /* let the caller do a getsockopt() if it wants it */
|
errno = 0; /* let the caller do a getsockopt() if it wants it */
|
||||||
@ -93,8 +95,10 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe,
|
|||||||
SPLICE_F_MOVE|SPLICE_F_NONBLOCK);
|
SPLICE_F_MOVE|SPLICE_F_NONBLOCK);
|
||||||
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
if (ret == 0)
|
if (ret == 0) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||||
goto out_read0;
|
goto out_read0;
|
||||||
|
}
|
||||||
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
/* there are two reasons for EAGAIN :
|
/* there are two reasons for EAGAIN :
|
||||||
@ -157,7 +161,6 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe,
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
out_read0:
|
out_read0:
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
|
||||||
conn_sock_read0(conn);
|
conn_sock_read0(conn);
|
||||||
conn->flags &= ~CO_FL_WAIT_L4_CONN;
|
conn->flags &= ~CO_FL_WAIT_L4_CONN;
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -179,7 +182,6 @@ int raw_sock_from_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pip
|
|||||||
|
|
||||||
if (conn->flags & CO_FL_SOCK_WR_SH) {
|
if (conn->flags & CO_FL_SOCK_WR_SH) {
|
||||||
/* it's already closed */
|
/* it's already closed */
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_snd_err);
|
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
|
||||||
errno = EPIPE;
|
errno = EPIPE;
|
||||||
conn_set_errno(conn, errno);
|
conn_set_errno(conn, errno);
|
||||||
@ -251,12 +253,14 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
|
|||||||
|
|
||||||
if (unlikely(!(fdtab[conn->handle.fd].state & FD_POLL_IN))) {
|
if (unlikely(!(fdtab[conn->handle.fd].state & FD_POLL_IN))) {
|
||||||
/* stop here if we reached the end of data */
|
/* stop here if we reached the end of data */
|
||||||
if ((fdtab[conn->handle.fd].state & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
|
if ((fdtab[conn->handle.fd].state & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_hup);
|
||||||
goto read0;
|
goto read0;
|
||||||
|
}
|
||||||
|
|
||||||
/* report error on POLL_ERR before connection establishment */
|
/* report error on POLL_ERR before connection establishment */
|
||||||
if ((fdtab[conn->handle.fd].state & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
|
if ((fdtab[conn->handle.fd].state & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_rcv_err);
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_connect_poll_err);
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
||||||
conn_set_errcode(conn, CO_ER_POLLERR);
|
conn_set_errcode(conn, CO_ER_POLLERR);
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -294,8 +298,10 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
|
|||||||
* to read an unlikely close from the client since we'll
|
* to read an unlikely close from the client since we'll
|
||||||
* close first anyway.
|
* close first anyway.
|
||||||
*/
|
*/
|
||||||
if (fdtab[conn->handle.fd].state & FD_POLL_HUP)
|
if (fdtab[conn->handle.fd].state & FD_POLL_HUP) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_hup);
|
||||||
goto read0;
|
goto read0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(fdtab[conn->handle.fd].state & FD_LINGER_RISK) ||
|
if (!(fdtab[conn->handle.fd].state & FD_LINGER_RISK) ||
|
||||||
(cur_poller.flags & HAP_POLL_F_RDHUP)) {
|
(cur_poller.flags & HAP_POLL_F_RDHUP)) {
|
||||||
@ -308,6 +314,7 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (ret == 0) {
|
else if (ret == 0) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||||
goto read0;
|
goto read0;
|
||||||
}
|
}
|
||||||
else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) {
|
else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) {
|
||||||
@ -330,7 +337,6 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
|
|||||||
return done;
|
return done;
|
||||||
|
|
||||||
read0:
|
read0:
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
|
||||||
conn_sock_read0(conn);
|
conn_sock_read0(conn);
|
||||||
conn->flags &= ~CO_FL_WAIT_L4_CONN;
|
conn->flags &= ~CO_FL_WAIT_L4_CONN;
|
||||||
|
|
||||||
@ -342,7 +348,7 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu
|
|||||||
* an error without checking.
|
* an error without checking.
|
||||||
*/
|
*/
|
||||||
if (unlikely(!done && fdtab[conn->handle.fd].state & FD_POLL_ERR)) {
|
if (unlikely(!done && fdtab[conn->handle.fd].state & FD_POLL_ERR)) {
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_rcv_err);
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_err);
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
||||||
conn_set_errcode(conn, CO_ER_POLLERR);
|
conn_set_errcode(conn, CO_ER_POLLERR);
|
||||||
}
|
}
|
||||||
@ -377,7 +383,7 @@ static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const s
|
|||||||
|
|
||||||
if (unlikely(fdtab[conn->handle.fd].state & FD_POLL_ERR)) {
|
if (unlikely(fdtab[conn->handle.fd].state & FD_POLL_ERR)) {
|
||||||
/* an error was reported on the FD, we can't send anymore */
|
/* an error was reported on the FD, we can't send anymore */
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_snd_err);
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_poll_err);
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_SOCK_RD_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_WR_SH | CO_FL_SOCK_RD_SH;
|
||||||
conn_set_errcode(conn, CO_ER_POLLERR);
|
conn_set_errcode(conn, CO_ER_POLLERR);
|
||||||
errno = EPIPE;
|
errno = EPIPE;
|
||||||
|
@ -988,9 +988,11 @@ int sock_conn_check(struct connection *conn)
|
|||||||
if (errno == EALREADY || errno == EINPROGRESS)
|
if (errno == EALREADY || errno == EINPROGRESS)
|
||||||
goto wait;
|
goto wait;
|
||||||
|
|
||||||
if (errno && errno != EISCONN)
|
if (errno && errno != EISCONN) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_connect_err);
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
/* The FD is ready now, we'll mark the connection as complete and
|
/* The FD is ready now, we'll mark the connection as complete and
|
||||||
@ -1007,7 +1009,6 @@ int sock_conn_check(struct connection *conn)
|
|||||||
/* Write error on the file descriptor. Report it to the connection
|
/* Write error on the file descriptor. Report it to the connection
|
||||||
* and disable polling on this FD.
|
* and disable polling on this FD.
|
||||||
*/
|
*/
|
||||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_connect_err);
|
|
||||||
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH;
|
||||||
HA_ATOMIC_AND(&fdtab[fd].state, ~FD_LINGER_RISK);
|
HA_ATOMIC_AND(&fdtab[fd].state, ~FD_LINGER_RISK);
|
||||||
fd_stop_both(fd);
|
fd_stop_both(fd);
|
||||||
@ -1018,8 +1019,10 @@ int sock_conn_check(struct connection *conn)
|
|||||||
* in some corner cases while the system disagrees and reports an error
|
* in some corner cases while the system disagrees and reports an error
|
||||||
* on the FD.
|
* on the FD.
|
||||||
*/
|
*/
|
||||||
if (fdtab[fd].state & FD_POLL_ERR)
|
if (fdtab[fd].state & FD_POLL_ERR) {
|
||||||
|
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_connect_poll_err);
|
||||||
goto out_error;
|
goto out_error;
|
||||||
|
}
|
||||||
|
|
||||||
fd_cant_send(fd);
|
fd_cant_send(fd);
|
||||||
fd_want_send(fd);
|
fd_want_send(fd);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user