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
@ -23,10 +23,10 @@ static const char *tevt_unknown_types[16] = {
|
||||
};
|
||||
|
||||
static const char *tevt_fd_types[16] = {
|
||||
[ 0] = "-", [ 1] = "shutw", [ 2] = "shutr", [ 3] = "rcv_err",
|
||||
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "conn_err",
|
||||
[ 8] = "intercepted", [ 9] = "-", [10] = "-", [11] = "-",
|
||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||
[ 0] = "-", [ 1] = "shutw", [ 2] = "shutr", [ 3] = "rcv_err",
|
||||
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "conn_err",
|
||||
[ 8] = "intercepted", [ 9] = "conn_poll_err", [10] = "poll_err", [11] = "poll_hup",
|
||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||
};
|
||||
|
||||
static const char *tevt_hs_types[16] = {
|
||||
|
@ -763,6 +763,10 @@ enum fd_term_event_type {
|
||||
/* unused: 5, 6 */
|
||||
fd_tevt_type_connect_err = 7,
|
||||
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 {
|
||||
|
@ -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))) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* report error on POLL_ERR before connection establishment */
|
||||
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_set_errcode(conn, CO_ER_POLLERR);
|
||||
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);
|
||||
|
||||
if (ret <= 0) {
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||
goto out_read0;
|
||||
}
|
||||
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
/* 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;
|
||||
|
||||
out_read0:
|
||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||
conn_sock_read0(conn);
|
||||
conn->flags &= ~CO_FL_WAIT_L4_CONN;
|
||||
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) {
|
||||
/* 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;
|
||||
errno = EPIPE;
|
||||
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))) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* report error on POLL_ERR before connection establishment */
|
||||
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_set_errcode(conn, CO_ER_POLLERR);
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
if (!(fdtab[conn->handle.fd].state & FD_LINGER_RISK) ||
|
||||
(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;
|
||||
}
|
||||
else if (ret == 0) {
|
||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||
goto read0;
|
||||
}
|
||||
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;
|
||||
|
||||
read0:
|
||||
conn_report_term_evt(conn, tevt_loc_fd, fd_tevt_type_shutr);
|
||||
conn_sock_read0(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.
|
||||
*/
|
||||
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_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)) {
|
||||
/* 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_set_errcode(conn, CO_ER_POLLERR);
|
||||
errno = EPIPE;
|
||||
|
@ -988,8 +988,10 @@ int sock_conn_check(struct connection *conn)
|
||||
if (errno == EALREADY || errno == EINPROGRESS)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
@ -1007,7 +1009,6 @@ int sock_conn_check(struct connection *conn)
|
||||
/* Write error on the file descriptor. Report it to the connection
|
||||
* 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;
|
||||
HA_ATOMIC_AND(&fdtab[fd].state, ~FD_LINGER_RISK);
|
||||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
fd_cant_send(fd);
|
||||
fd_want_send(fd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user