MINOR: conn-stream: Make cs_detach_* private and use cs_destroy() from outside

A conn-stream is never detached from an endpoint or an application alone,
except on a reset. Thus, to avoid any error, these functions are now
private. And cs_destroy() function is added to destroy a conn-stream. This
function is called when a stream is released, on the front and back
conn-streams, and when a health-check is finished.
This commit is contained in:
Christopher Faulet 2022-04-21 14:22:53 +02:00
parent c6b60f1e00
commit eb50c01fef
5 changed files with 43 additions and 22 deletions

View File

@ -47,9 +47,8 @@ void cs_free(struct conn_stream *cs);
int cs_attach_mux(struct conn_stream *cs, void *target, void *ctx); int cs_attach_mux(struct conn_stream *cs, void *target, void *ctx);
int cs_attach_strm(struct conn_stream *cs, struct stream *strm); int cs_attach_strm(struct conn_stream *cs, struct stream *strm);
void cs_destroy(struct conn_stream *cs);
int cs_reset_endp(struct conn_stream *cs); int cs_reset_endp(struct conn_stream *cs);
void cs_detach_endp(struct conn_stream *cs);
void cs_detach_app(struct conn_stream *cs);
struct appctx *cs_applet_create(struct conn_stream *cs, struct applet *app); struct appctx *cs_applet_create(struct conn_stream *cs, struct applet *app);
void cs_applet_shut(struct conn_stream *cs); void cs_applet_shut(struct conn_stream *cs);

View File

@ -1199,8 +1199,7 @@ struct task *process_chk_conn(struct task *t, void *context, unsigned int state)
* the tasklet * the tasklet
*/ */
tasklet_remove_from_tasklet_list(check->wait_list.tasklet); tasklet_remove_from_tasklet_list(check->wait_list.tasklet);
cs_detach_endp(cs); cs_destroy(cs);
cs_detach_app(cs);
cs = check->cs = NULL; cs = check->cs = NULL;
conn = NULL; conn = NULL;
} }
@ -1364,8 +1363,7 @@ void free_check(struct check *check)
check_release_buf(check, &check->bi); check_release_buf(check, &check->bi);
check_release_buf(check, &check->bo); check_release_buf(check, &check->bo);
if (check->cs) { if (check->cs) {
cs_detach_endp(check->cs); cs_destroy(check->cs);
cs_detach_app(check->cs);
check->cs = NULL; check->cs = NULL;
} }
} }

View File

@ -244,13 +244,18 @@ void cs_free(struct conn_stream *cs)
pool_free(pool_head_connstream, cs); pool_free(pool_head_connstream, cs);
} }
/* Conditionally removes a conn-stream if it is detached and it there is no app /* Conditionally removes a conn-stream if it is detached and if there is no app
* layer defined. Except on error path, this one must be used. * layer defined. Except on error path, this one must be used. if release, the
* pointer on the CS is set to NULL.
*/ */
static void cs_free_cond(struct conn_stream *cs) static void cs_free_cond(struct conn_stream **csp)
{ {
if (!cs->app && (!cs->endp || (cs->endp->flags & CS_EP_DETACHED))) struct conn_stream *cs = *csp;
if (!cs->app && (!cs->endp || (cs->endp->flags & CS_EP_DETACHED))) {
cs_free(cs); cs_free(cs);
*csp = NULL;
}
} }
@ -344,8 +349,13 @@ int cs_attach_strm(struct conn_stream *cs, struct stream *strm)
* endpoint is reset and flag as detached. If the app layer is also detached, * endpoint is reset and flag as detached. If the app layer is also detached,
* the conn-stream is released. * the conn-stream is released.
*/ */
void cs_detach_endp(struct conn_stream *cs) static void cs_detach_endp(struct conn_stream **csp)
{ {
struct conn_stream *cs = *csp;
if (!cs)
return;
if (!cs->endp) if (!cs->endp)
goto reset_cs; goto reset_cs;
@ -394,14 +404,19 @@ void cs_detach_endp(struct conn_stream *cs)
if (cs_strm(cs)) if (cs_strm(cs))
cs->ops = &cs_app_embedded_ops; cs->ops = &cs_app_embedded_ops;
cs->data_cb = NULL; cs->data_cb = NULL;
cs_free_cond(cs); cs_free_cond(csp);
} }
/* Detaches the conn_stream from the app layer. If there is no endpoint attached /* Detaches the conn_stream from the app layer. If there is no endpoint attached
* to the conn_stream * to the conn_stream
*/ */
void cs_detach_app(struct conn_stream *cs) static void cs_detach_app(struct conn_stream **csp)
{ {
struct conn_stream *cs = *csp;
if (!cs)
return;
cs->app = NULL; cs->app = NULL;
cs->data_cb = NULL; cs->data_cb = NULL;
sockaddr_free(&cs->src); sockaddr_free(&cs->src);
@ -411,7 +426,17 @@ void cs_detach_app(struct conn_stream *cs)
tasklet_free(cs->wait_event.tasklet); tasklet_free(cs->wait_event.tasklet);
cs->wait_event.tasklet = NULL; cs->wait_event.tasklet = NULL;
cs->wait_event.events = 0; cs->wait_event.events = 0;
cs_free_cond(cs); cs_free_cond(csp);
}
/* Destroy the conn_stream. It is detached from its endpoint and its
* application. After this call, the conn_stream must be considered as released.
*/
void cs_destroy(struct conn_stream *cs)
{
cs_detach_endp(&cs);
cs_detach_app(&cs);
BUG_ON_HOT(cs);
} }
/* Resets the conn-stream endpoint. It happens when the app layer want to renew /* Resets the conn-stream endpoint. It happens when the app layer want to renew
@ -426,9 +451,10 @@ int cs_reset_endp(struct conn_stream *cs)
if (!__cs_endp_target(cs)) { if (!__cs_endp_target(cs)) {
/* endpoint not attached or attached to a mux with no /* endpoint not attached or attached to a mux with no
* target. Thus the endpoint will not be release but just * target. Thus the endpoint will not be release but just
* reset * reset. The app is still attached, the cs will not be
* released.
*/ */
cs_detach_endp(cs); cs_detach_endp(&cs);
return 0; return 0;
} }
@ -440,7 +466,8 @@ int cs_reset_endp(struct conn_stream *cs)
return -1; return -1;
} }
cs_detach_endp(cs); /* The app is still attached, the cs will not be released */
cs_detach_endp(&cs);
BUG_ON(cs->endp); BUG_ON(cs->endp);
cs->endp = new_endp; cs->endp = new_endp;
cs->endp->flags |= CS_EP_DETACHED; cs->endp->flags |= CS_EP_DETACHED;

View File

@ -519,7 +519,6 @@ struct appctx *httpclient_start(struct httpclient *hc)
s->target = &httpclient_srv_ssl->obj_type; s->target = &httpclient_srv_ssl->obj_type;
#else #else
ha_alert("httpclient: OpenSSL is not available %s:%d.\n", __FUNCTION__, __LINE__); ha_alert("httpclient: OpenSSL is not available %s:%d.\n", __FUNCTION__, __LINE__);
cs_detach_app(cs);
LIST_DELETE(&s->list); LIST_DELETE(&s->list);
pool_free(pool_head_stream, s); pool_free(pool_head_stream, s);
cs_free(cs); cs_free(cs);

View File

@ -714,10 +714,8 @@ static void stream_free(struct stream *s)
/* FIXME: Handle it in appctx_free ??? */ /* FIXME: Handle it in appctx_free ??? */
must_free_sess = objt_appctx(sess->origin) && sess->origin == __cs_endp_target(s->csf); must_free_sess = objt_appctx(sess->origin) && sess->origin == __cs_endp_target(s->csf);
cs_detach_endp(s->csb); cs_destroy(s->csb);
cs_detach_endp(s->csf); cs_destroy(s->csf);
cs_detach_app(s->csb);
cs_detach_app(s->csf);
if (must_free_sess) { if (must_free_sess) {
sess->origin = NULL; sess->origin = NULL;