MINOR: connection: Be prepared to handle conn-stream with no connection
The conn-stream will progressively replace the stream-interface. Thus, a
stream will have to allocate the backend conn-stream during its
creation. This means it will be possible to have a conn-stream with no
connection. To prepare this change, we test the conn-stream's connection
when we retrieve it.
diff --git a/src/check.c b/src/check.c
index cb1be9b..97d340a 100644
--- a/src/check.c
+++ b/src/check.c
@@ -233,7 +233,9 @@
if (check->cs) {
- chunk_appendf(&trace_buf, " - conn=%p(0x%08x)", check->cs->conn, check->cs->conn->flags);
+ struct connection *conn = cs_conn(check->cs);
+
+ chunk_appendf(&trace_buf, " - conn=%p(0x%08x)", conn, conn ? conn->flags : 0);
chunk_appendf(&trace_buf, " cs=%p(0x%08x)", check->cs, check->cs->flags);
}
@@ -791,7 +793,7 @@
retrieve_errno_from_socket(conn);
if (conn && !(conn->flags & CO_FL_ERROR) &&
- !(cs->flags & CS_FL_ERROR) && !expired)
+ cs && !(cs->flags & CS_FL_ERROR) && !expired)
return;
TRACE_ENTER(CHK_EV_HCHK_END|CHK_EV_HCHK_ERR, check, 0, 0, (size_t[]){expired});
@@ -904,7 +906,7 @@
set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
}
- if (!conn || !conn->ctrl) {
+ if (!cs || !conn || !conn->ctrl) {
/* error before any connection attempt (connection allocation error or no control layer) */
set_server_check_status(check, HCHK_STATUS_SOCKERR, err_msg);
}
@@ -1016,7 +1018,7 @@
*/
static int wake_srv_chk(struct conn_stream *cs)
{
- struct connection *conn = cs->conn;
+ struct connection *conn;
struct check *check = cs->data;
struct email_alertq *q = container_of(check, typeof(*q), check);
int ret = 0;
@@ -1031,9 +1033,9 @@
ret = tcpcheck_main(check);
cs = check->cs;
- conn = cs->conn;
+ conn = cs_conn(cs);
- if (unlikely(conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) {
+ if (unlikely(!conn || !cs || conn->flags & CO_FL_ERROR || cs->flags & CS_FL_ERROR)) {
/* We may get error reports bypassing the I/O handlers, typically
* the case when sending a pure TCP check which fails, then the I/O
* handlers above are not called. This is completely handled by the
@@ -1053,7 +1055,7 @@
ret = -1;
if (check->wait_list.events)
- cs->conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
+ conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
/* We may have been scheduled to run, and the
* I/O handler expects to have a cs, so remove
@@ -1171,6 +1173,8 @@
TRACE_STATE("health-check complete or aborted", CHK_EV_TASK_WAKE|CHK_EV_HCHK_END, check);
check->current_step = NULL;
+ cs = check->cs;
+ conn = cs_conn(cs);
if (conn && conn->xprt) {
/* The check was aborted and the connection was not yet closed.
@@ -1182,8 +1186,8 @@
}
if (cs) {
- if (check->wait_list.events)
- cs->conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
+ if (conn && check->wait_list.events)
+ conn->mux->unsubscribe(cs, check->wait_list.events, &check->wait_list);
/* We may have been scheduled to run, and the
* I/O handler expects to have a cs, so remove
* the tasklet
@@ -1352,7 +1356,10 @@
check_release_buf(check, &check->bi);
check_release_buf(check, &check->bo);
if (check->cs) {
- ha_free(&check->cs->conn);
+ struct connection *conn = cs_conn(check->cs);
+
+ if (conn)
+ conn_free(conn);
cs_free(check->cs);
check->cs = NULL;
}