Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New timeout nomenclature #3817

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions bin/varnishd/cache/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,9 @@ struct busyobj {
#include "tbl/bo_flags.h"

/* Timeouts */
vtim_dur connect_timeout;
vtim_dur first_byte_timeout;
vtim_dur between_bytes_timeout;
vtim_dur bereq_connect_timeout;
vtim_dur beresp_start_timeout;
vtim_dur beresp_idle_timeout;

/* Timers */
vtim_real t_first; /* First timestamp logged */
Expand Down Expand Up @@ -562,13 +562,16 @@ struct sess {

vtim_real t_open; /* fd accepted */
vtim_real t_idle; /* fd accepted or resp sent */
vtim_dur timeout_idle;
vtim_dur timeout_linger;
vtim_dur send_timeout;
vtim_dur idle_send_timeout;
vtim_dur idle_timeout;
vtim_dur linger_interrupt;
vtim_dur resp_send_timeout;
vtim_dur resp_idle_interrupt;
};

#define SESS_TMO(sp, tmo) \
(isnan((sp)->tmo) ? cache_param->sess_##tmo : (sp)->tmo)

#define RESP_TMO(sp, tmo) \
(isnan((sp)->tmo) ? cache_param->tmo : (sp)->tmo)

/* Prototypes etc ----------------------------------------------------*/
Expand Down
4 changes: 2 additions & 2 deletions bin/varnishd/cache/cache_acceptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ vca_sock_opt_init(void)
SET_VAL(SO_LINGER, so, lg, disable_so_linger);
SET_VAL(SO_KEEPALIVE, so, i, enable_so_keepalive);
NEW_VAL(SO_SNDTIMEO, so, tv,
VTIM_timeval(cache_param->idle_send_timeout));
VTIM_timeval(cache_param->resp_idle_interrupt));
NEW_VAL(SO_RCVTIMEO, so, tv,
VTIM_timeval(cache_param->timeout_idle));
VTIM_timeval(cache_param->sess_idle_timeout));
SET_VAL(TCP_NODELAY, so, i, enable_tcp_nodelay);
#if defined(HAVE_TCP_KEEP)
NEW_VAL(TCP_KEEPIDLE, so, i,
Expand Down
12 changes: 6 additions & 6 deletions bin/varnishd/cache/cache_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
bo->htc->doclose = SC_NULL;
CHECK_OBJ_NOTNULL(bo->htc->doclose, STREAM_CLOSE_MAGIC);

FIND_TMO(connect_timeout, tmod, bo, bp);
FIND_TMO(bereq_connect_timeout, tmod, bo, bp);
pfd = VCP_Get(bp->conn_pool, tmod, wrk, force_fresh, &err);
if (pfd == NULL) {
Lck_Lock(bp->director->mtx);
Expand Down Expand Up @@ -211,10 +211,10 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
bo->htc->priv = pfd;
bo->htc->rfd = fdp;
bo->htc->doclose = SC_NULL;
FIND_TMO(first_byte_timeout,
bo->htc->first_byte_timeout, bo, bp);
FIND_TMO(between_bytes_timeout,
bo->htc->between_bytes_timeout, bo, bp);
FIND_TMO(beresp_start_timeout,
bo->htc->beresp_start_timeout, bo, bp);
FIND_TMO(beresp_idle_timeout,
bo->htc->beresp_idle_timeout, bo, bp);
return (pfd);
}

Expand Down Expand Up @@ -303,7 +303,7 @@ vbe_dir_gethdrs(VRT_CTX, VCL_BACKEND d)

if (i == 0 && PFD_State(pfd) != PFD_STATE_USED) {
if (VCP_Wait(wrk, pfd, VTIM_real() +
bo->htc->first_byte_timeout) != 0) {
bo->htc->beresp_start_timeout) != 0) {
bo->htc->doclose = SC_RX_TIMEOUT;
VSLb(bo->vsl, SLT_FetchError,
"first byte timeout (reused connection)");
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishd/cache/cache_conn_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ VCP_Recycle(const struct worker *wrk, struct pfd **pfdp)
pfd->waited->idle = VTIM_real();
pfd->state = PFD_STATE_AVAIL;
pfd->waited->func = vcp_handle;
pfd->waited->tmo = cache_param->backend_idle_timeout;
pfd->waited->tmo = cache_param->backend_pool_timeout;
if (Wait_Enter(wrk->pool->waiter, pfd->waited)) {
cp->methods->close(pfd);
memset(pfd, 0x33, sizeof *pfd);
Expand Down
8 changes: 4 additions & 4 deletions bin/varnishd/cache/cache_panic.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ pan_htc(struct vsb *vsb, const struct http_conn *htc)
(intmax_t)htc->content_length);
VSB_printf(vsb, "body_status = %s,\n",
htc->body_status ? htc->body_status->name : "NULL");
VSB_printf(vsb, "first_byte_timeout = %f,\n",
htc->first_byte_timeout);
VSB_printf(vsb, "between_bytes_timeout = %f,\n",
htc->between_bytes_timeout);
VSB_printf(vsb, "beresp_start_timeout = %f,\n",
htc->beresp_start_timeout);
VSB_printf(vsb, "beresp_idle_timeout = %f,\n",
htc->beresp_idle_timeout);
VSB_indent(vsb, -2);
VSB_cat(vsb, "},\n");
}
Expand Down
10 changes: 5 additions & 5 deletions bin/varnishd/cache/cache_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,10 @@ SES_New(struct pool *pp)

sp->t_open = NAN;
sp->t_idle = NAN;
sp->timeout_idle = NAN;
sp->timeout_linger = NAN;
sp->send_timeout = NAN;
sp->idle_send_timeout = NAN;
sp->idle_timeout = NAN;
sp->linger_interrupt = NAN;
sp->resp_send_timeout = NAN;
sp->resp_idle_interrupt = NAN;
Lck_New(&sp->mtx, lck_sess);
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
return (sp);
Expand Down Expand Up @@ -529,7 +529,7 @@ SES_Wait(struct sess *sp, const struct transport *xp)
wp->priv2 = (uintptr_t)xp;
wp->idle = sp->t_idle;
wp->func = ses_handle;
wp->tmo = SESS_TMO(sp, timeout_idle);
wp->tmo = SESS_TMO(sp, idle_timeout);
if (Wait_Enter(pp->waiter, wp))
SES_Delete(sp, SC_PIPE_OVERFLOW, NAN);
}
Expand Down
4 changes: 2 additions & 2 deletions bin/varnishd/cache/cache_varnishd.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ struct http_conn {
void *priv;

/* Timeouts */
vtim_dur first_byte_timeout;
vtim_dur between_bytes_timeout;
vtim_dur beresp_start_timeout;
vtim_dur beresp_idle_timeout;
};

enum htc_status_e {
Expand Down
68 changes: 44 additions & 24 deletions bin/varnishd/cache/cache_vrt_var.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,28 +331,28 @@ VRT_l_client_identity(VRT_CTX, const char *str, VCL_STRANDS s)

/*--------------------------------------------------------------------*/

#define BEREQ_TIMEOUT(which) \
#define FETCH_TIMEOUT(msg, which) \
VCL_VOID \
VRT_l_bereq_##which(VRT_CTX, VCL_DURATION num) \
VRT_l_##msg##_##which(VRT_CTX, VCL_DURATION num) \
{ \
\
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); \
ctx->bo->which = (num > 0.0 ? num : 0.0); \
ctx->bo->msg##_##which = (num > 0.0 ? num : 0.0); \
} \
\
VCL_DURATION \
VRT_r_bereq_##which(VRT_CTX) \
VRT_r_##msg##_##which(VRT_CTX) \
{ \
\
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC); \
return (ctx->bo->which); \
return (ctx->bo->msg##_##which); \
}

BEREQ_TIMEOUT(connect_timeout)
BEREQ_TIMEOUT(first_byte_timeout)
BEREQ_TIMEOUT(between_bytes_timeout)
FETCH_TIMEOUT(bereq, connect_timeout)
FETCH_TIMEOUT(beresp, idle_timeout)
FETCH_TIMEOUT(beresp, start_timeout)

/*--------------------------------------------------------------------*/

Expand Down Expand Up @@ -973,6 +973,37 @@ VRT_r_resp_do_esi(VRT_CTX)
return (!ctx->req->disable_esi);
}

/*--------------------------------------------------------------------
* XXX: Response timeouts are currently broken since they operate at
* the session level. Customizing a response timeout for one client
* transaction will still leak into the next HTTP/1 transaction or
* simply result in concurrent meddlings on h2 sessions. In particular
* socket options should only apply to HTTP/1 and this should probably
* be moved to protocol-specific code.
*/

#define RESP_TIMEOUT(x, setter) \
VCL_VOID \
VRT_l_resp_##x(VRT_CTX, VCL_DURATION d) \
{ \
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC); \
d = vmax(d, 0.0); \
setter; \
ctx->sp->resp_##x = d; \
} \
\
VCL_DURATION \
VRT_r_resp_##x(VRT_CTX) \
{ \
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC); \
return (RESP_TMO(ctx->sp, resp_##x)); \
}

RESP_TIMEOUT(idle_interrupt, VTCP_set_send_timeout(ctx->sp->fd, d))
RESP_TIMEOUT(send_timeout, )

/*--------------------------------------------------------------------*/

#define VRT_BODY_L(which) \
Expand Down Expand Up @@ -1050,34 +1081,23 @@ HTTP_VAR(beresp)

/*--------------------------------------------------------------------*/

static inline void
set_idle_send_timeout(const struct sess *sp, VCL_DURATION d)
{
struct timeval tv = VTIM_timeval(d);
VTCP_Assert(setsockopt(sp->fd, SOL_SOCKET, SO_SNDTIMEO,
&tv, sizeof tv));
}

#define SESS_VAR_DUR(x, setter) \
#define SESS_VAR_DUR(x) \
VCL_VOID \
VRT_l_sess_##x(VRT_CTX, VCL_DURATION d) \
VRT_l_sess_##x(VRT_CTX, VCL_DURATION d) \
{ \
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC); \
d = vmax(d, 0.0); \
setter; \
ctx->sp->x = d; \
} \
\
VCL_DURATION \
VRT_r_sess_##x(VRT_CTX) \
VRT_r_sess_##x(VRT_CTX) \
{ \
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
CHECK_OBJ_NOTNULL(ctx->sp, SESS_MAGIC); \
return (SESS_TMO(ctx->sp, x)); \
}

SESS_VAR_DUR(timeout_idle, )
SESS_VAR_DUR(timeout_linger, )
SESS_VAR_DUR(send_timeout, )
SESS_VAR_DUR(idle_send_timeout, set_idle_send_timeout(ctx->sp, d))
SESS_VAR_DUR(idle_timeout)
SESS_VAR_DUR(linger_interrupt)
2 changes: 1 addition & 1 deletion bin/varnishd/http1/cache_http1_deliver.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ V1D_Deliver(struct req *req, struct boc *boc, int sendbody)

AZ(req->wrk->v1l);
V1L_Open(req->wrk, req->wrk->aws, &req->sp->fd, req->vsl,
req->t_prev + SESS_TMO(req->sp, send_timeout),
req->t_prev + RESP_TMO(req->sp, resp_send_timeout),
cache_param->http1_iovs);

if (WS_Overflowed(req->wrk->aws)) {
Expand Down
8 changes: 4 additions & 4 deletions bin/varnishd/http1/cache_http1_fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ V1F_SendReq(struct worker *wrk, struct busyobj *bo, uint64_t *ctr_hdrbytes,
}

VTCP_blocking(*htc->rfd); /* XXX: we should timeout instead */
/* XXX: need a send_timeout for the backend side */
/* XXX: need a bereq_send_timeout */
V1L_Open(wrk, wrk->aws, htc->rfd, bo->vsl, nan(""), 0);
hdrbytes = HTTP1_Write(wrk, hp, HTTP1_Req);

Expand Down Expand Up @@ -190,9 +190,9 @@ V1F_FetchRespHdr(struct busyobj *bo)
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);

t = VTIM_real() + htc->first_byte_timeout;
t = VTIM_real() + htc->beresp_start_timeout;
hs = HTC_RxStuff(htc, HTTP1_Complete, NULL, NULL,
t, NAN, htc->between_bytes_timeout, cache_param->http_resp_size);
t, NAN, htc->beresp_idle_timeout, cache_param->http_resp_size);
if (hs != HTC_S_COMPLETE) {
bo->acct.beresp_hdrbytes +=
htc->rxbuf_e - htc->rxbuf_b;
Expand Down Expand Up @@ -225,7 +225,7 @@ V1F_FetchRespHdr(struct busyobj *bo)
}
return (htc->rxbuf_e == htc->rxbuf_b ? 1 : -1);
}
VTCP_set_read_timeout(*htc->rfd, htc->between_bytes_timeout);
VTCP_set_read_timeout(*htc->rfd, htc->beresp_idle_timeout);

hp = bo->beresp;

Expand Down
4 changes: 2 additions & 2 deletions bin/varnishd/http1/cache_http1_fsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,8 @@ HTTP1_Session(struct worker *wrk, struct req *req)

hs = HTC_RxStuff(req->htc, HTTP1_Complete,
&req->t_first, &req->t_req,
sp->t_idle + SESS_TMO(sp, timeout_linger),
sp->t_idle + SESS_TMO(sp, timeout_idle),
sp->t_idle + SESS_TMO(sp, linger_interrupt),
sp->t_idle + SESS_TMO(sp, idle_timeout),
NAN,
cache_param->http_req_size);
assert(!WS_IsReserved(req->htc->ws));
Expand Down
2 changes: 1 addition & 1 deletion bin/varnishd/http1/cache_http1_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ V1P_Process(const struct req *req, int fd, struct v1p_acct *v1a)
fds[0].revents = 0;
fds[1].revents = 0;
i = poll(fds, 2,
(int)(cache_param->pipe_timeout * 1e3));
(int)(cache_param->pipe_idle_timeout * 1e3));
if (i < 1)
break;
if (fds[0].revents &&
Expand Down
14 changes: 7 additions & 7 deletions bin/varnishd/http2/cache_http2_proto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
break;

i = Lck_CondWaitTimeout(r2->cond, &h2->sess->mtx,
SESS_TMO(h2->sess, timeout_idle));
SESS_TMO(h2->sess, idle_timeout));
if (i == ETIMEDOUT) {
retval = VFP_ERROR;
break;
Expand Down Expand Up @@ -1241,7 +1241,7 @@ h2_stream_tmo(struct h2_sess *h2, const struct h2_req *r2, vtim_real now)
CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
Lck_AssertHeld(&h2->sess->mtx);

/* NB: when now is NAN, it means that idle_send_timeout was hit
/* NB: when now is NAN, it means that resp_idle_interrupt was hit
* on a lock condwait operation.
*/
if (isnan(now))
Expand All @@ -1251,17 +1251,17 @@ h2_stream_tmo(struct h2_sess *h2, const struct h2_req *r2, vtim_real now)
return (0);

if (isnan(now) || (r2->t_winupd != 0 &&
now - r2->t_winupd > SESS_TMO(h2->sess, idle_send_timeout))) {
now - r2->t_winupd > RESP_TMO(h2->sess, resp_idle_interrupt))) {
VSLb(h2->vsl, SLT_Debug,
"H2: stream %u: Hit idle_send_timeout waiting for"
"H2: stream %u: Hit resp_idle_interrupt waiting for"
" WINDOW_UPDATE", r2->stream);
r = 1;
}

if (r == 0 && r2->t_send != 0 &&
now - r2->t_send > SESS_TMO(h2->sess, send_timeout)) {
now - r2->t_send > RESP_TMO(h2->sess, resp_send_timeout)) {
VSLb(h2->vsl, SLT_Debug,
"H2: stream %u: Hit send_timeout", r2->stream);
"H2: stream %u: Hit resp_send_timeout", r2->stream);
r = 1;
}

Expand Down Expand Up @@ -1365,7 +1365,7 @@ h2_rxframe(struct worker *wrk, struct h2_sess *h2)
h2->sess->t_idle = VTIM_real();
hs = HTC_RxStuff(h2->htc, h2_frame_complete,
NULL, NULL, NAN,
h2->sess->t_idle + SESS_TMO(h2->sess, timeout_idle),
h2->sess->t_idle + SESS_TMO(h2->sess, idle_timeout),
NAN, h2->local_settings.max_frame_size + 9);
switch (hs) {
case HTC_S_COMPLETE:
Expand Down
12 changes: 6 additions & 6 deletions bin/varnishd/http2/cache_http2_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ h2_cond_wait(pthread_cond_t *cond, struct h2_sess *h2, struct h2_req *r2)

Lck_AssertHeld(&h2->sess->mtx);

if (cache_param->idle_send_timeout > 0.)
tmo = cache_param->idle_send_timeout;
if (cache_param->resp_idle_interrupt > 0.)
tmo = cache_param->resp_idle_interrupt;

r = Lck_CondWaitTimeout(cond, &h2->sess->mtx, tmo);
assert(r == 0 || r == ETIMEDOUT);

now = VTIM_real();

/* NB: when we grab idle_send_timeout before acquiring the session
* lock we may time out, but once we wake up both send_timeout and
* idle_send_timeout may have changed meanwhile. For this reason
/* NB: when we grab resp_idle_interrupt before acquiring the session
* lock we may time out, but once we wake up both resp_send_timeout
* and resp_idle_interrupt may have changed meanwhile. For this reason
* h2_stream_tmo() may not log what timed out and we need to call
* again with a magic NAN "now" that indicates to h2_stream_tmo()
* that the stream reached the idle_send_timeout via the lock and
* that the stream reached the resp_idle_interrupt via the lock and
* force it to log it.
*/
if (h2_stream_tmo(h2, r2, now))
Expand Down
5 changes: 3 additions & 2 deletions bin/varnishd/http2/cache_http2_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,9 @@ h2_ou_session(struct worker *wrk, struct h2_sess *h2,

/* Wait for PRISM response */
hs = HTC_RxStuff(h2->htc, H2_prism_complete,
NULL, NULL, NAN, h2->sess->t_idle + cache_param->timeout_idle, NAN,
sizeof H2_prism);
NULL, NULL, NAN,
h2->sess->t_idle + cache_param->sess_idle_timeout,
NAN, sizeof H2_prism);
if (hs != HTC_S_COMPLETE) {
VSLb(h2->vsl, SLT_Debug, "H2: No/Bad OU PRISM (hs=%d)", hs);
r2->scheduled = 0;
Expand Down
Loading