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

Backport series for 7.6.1 #4222

Merged
merged 14 commits into from
Nov 7, 2024
Merged
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
61 changes: 18 additions & 43 deletions bin/varnishd/cache/cache_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,28 +139,13 @@ VBE_Connect_Error(struct VSC_vbe *vsc, int err)

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

int
VBE_is_ah_auto (const struct backend *bp)
{
CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
return (bp->director->vdir->admin_health == VDI_AH_AUTO);
}

void
VBE_connwait_signal_all(const struct backend *bp)
static void
vbe_connwait_broadcast(const struct backend *bp)
{
struct connwait *cw;
unsigned wait_limit;
vtim_dur wait_tmod;

CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);

FIND_BE_PARAM(backend_wait_limit, wait_limit, bp);
FIND_BE_TMO(backend_wait_timeout, wait_tmod, bp);

if (wait_limit == 0 || wait_tmod <= 0)
return;

Lck_Lock(bp->director->mtx);
VTAILQ_FOREACH(cw, &bp->cw_head, cw_list) {
CHECK_OBJ(cw, CONNWAIT_MAGIC);
Expand All @@ -187,16 +172,6 @@ vbe_connwait_signal_locked(const struct backend *bp)
}
}

static void
vbe_connwait_dequeue_locked(struct backend *bp, struct connwait *cw)
{
Lck_AssertHeld(bp->director->mtx);
assert(cw->cw_state == CW_QUEUED);
VTAILQ_REMOVE(&bp->cw_head, cw, cw_list);
vbe_connwait_signal_locked(bp);
cw->cw_state = CW_DEQUEUED;
}

static void
vbe_connwait_fini(struct connwait *cw)
{
Expand Down Expand Up @@ -260,13 +235,17 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
err = Lck_CondWaitUntil(&cw->cw_cond, bp->director->mtx,
wait_end);
} while (err == EINTR);
assert(cw->cw_state == CW_QUEUED);
VTAILQ_REMOVE(&bp->cw_head, cw, cw_list);
cw->cw_state = CW_DEQUEUED;
bp->cw_count--;
if ((err != 0 && BE_BUSY(bp)) || !VRT_Healthy(ctx, dir, NULL)) {
VTAILQ_REMOVE(&bp->cw_head, cw, cw_list);
VSC_C_main->backend_wait_fail++;
cw->cw_state = CW_BE_BUSY;
}
}
if (cw->cw_state != CW_BE_BUSY)
bp->n_conn++;
Lck_Unlock(bp->director->mtx);

if (cw->cw_state == CW_BE_BUSY) {
Expand All @@ -284,11 +263,10 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
if (bo->htc == NULL) {
VSLb(bo->vsl, SLT_FetchError, "out of workspace");
/* XXX: counter ? */
if (cw->cw_state == CW_QUEUED) {
Lck_Lock(bp->director->mtx);
vbe_connwait_dequeue_locked(bp, cw);
Lck_Unlock(bp->director->mtx);
}
Lck_Lock(bp->director->mtx);
bp->n_conn--;
vbe_connwait_signal_locked(bp);
Lck_Unlock(bp->director->mtx);
vbe_connwait_fini(cw);
return (NULL);
}
Expand All @@ -300,17 +278,14 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
if (pfd == NULL) {
Lck_Lock(bp->director->mtx);
VBE_Connect_Error(bp->vsc, err);
bp->n_conn--;
vbe_connwait_signal_locked(bp);
Lck_Unlock(bp->director->mtx);
VSLb(bo->vsl, SLT_FetchError,
"backend %s: fail errno %d (%s)",
VRT_BACKEND_string(dir), err, VAS_errtxt(err));
VSC_C_main->backend_fail++;
bo->htc = NULL;
if (cw->cw_state == CW_QUEUED) {
Lck_Lock(bp->director->mtx);
vbe_connwait_dequeue_locked(bp, cw);
Lck_Unlock(bp->director->mtx);
}
vbe_connwait_fini(cw);
return (NULL);
}
Expand All @@ -321,12 +296,8 @@ vbe_dir_getfd(VRT_CTX, struct worker *wrk, VCL_BACKEND dir, struct backend *bp,
assert(*fdp >= 0);

Lck_Lock(bp->director->mtx);
bp->n_conn++;
bp->vsc->conn++;
bp->vsc->req++;
if (cw->cw_state == CW_QUEUED)
vbe_connwait_dequeue_locked(bp, cw);

Lck_Unlock(bp->director->mtx);

CHECK_OBJ_NOTNULL(bo->htc->doclose, STREAM_CLOSE_MAGIC);
Expand Down Expand Up @@ -582,6 +553,11 @@ vbe_dir_event(const struct director *d, enum vcl_event_e ev)
VRT_VSC_Hide(bp->vsc_seg);
} else if (ev == VCL_EVENT_DISCARD) {
VRT_DelDirector(&bp->director);
} else if (ev == VDI_EVENT_SICK) {
const struct vdi_ahealth *ah = d->vdir->admin_health;

if (ah == VDI_AH_SICK || (ah == VDI_AH_AUTO && bp->sick))
vbe_connwait_broadcast(bp);
}
}

Expand Down Expand Up @@ -682,7 +658,6 @@ vbe_healthy(VRT_CTX, VCL_BACKEND d, VCL_TIME *t)
return (!bp->sick);
}


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

Expand Down
6 changes: 2 additions & 4 deletions bin/varnishd/cache/cache_backend_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,8 @@ VBP_Update_Backend(struct vbp_target *vt)
i = (vt->good < vt->threshold);
chg = (i != vt->backend->sick);
vt->backend->sick = i;
if (i && chg && (vt->backend->director != NULL &&
VBE_is_ah_auto(vt->backend))) {
VBE_connwait_signal_all(vt->backend);
}
if (i && chg && vt->backend->director != NULL)
VDI_Event(vt->backend->director, VDI_EVENT_SICK);

AN(vt->backend->vcl_name);
VSL(SLT_Backend_health, NO_VXID,
Expand Down
8 changes: 1 addition & 7 deletions bin/varnishd/cache/cache_director.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,6 @@ static int v_matchproto_(vcl_be_func)
do_set_health(struct cli *cli, struct director *d, void *priv)
{
struct set_health *sh;
struct vrt_ctx *ctx;

(void)cli;
CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
Expand All @@ -488,12 +487,7 @@ do_set_health(struct cli *cli, struct director *d, void *priv)
if (d->vdir->admin_health != sh->ah) {
d->vdir->health_changed = VTIM_real();
d->vdir->admin_health = sh->ah;
ctx = VCL_Get_CliCtx(0);
if (sh->ah == VDI_AH_SICK || (sh->ah == VDI_AH_AUTO &&
d->vdir->methods->healthy != NULL &&
!d->vdir->methods->healthy(ctx, d, NULL))) {
VBE_connwait_signal_all(d->priv);
}
VDI_Event(d, VDI_EVENT_SICK);
}
return (0);
}
Expand Down
4 changes: 0 additions & 4 deletions bin/varnishd/cache/cache_varnishd.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,7 @@ void VCA_Init(void);
void VCA_Shutdown(void);

/* cache_backend.c */
struct backend;

void VBE_InitCfg(void);
void VBE_connwait_signal_all(const struct backend *bp);
int VBE_is_ah_auto(const struct backend *bp);

/* cache_ban.c */

Expand Down
26 changes: 26 additions & 0 deletions bin/varnishd/common/common_vsmw.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <time.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>

#include "vdef.h"
Expand Down Expand Up @@ -274,6 +275,30 @@ vsmw_delseg(struct vsmw *vsmw, struct vsmwseg *seg)

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

#ifdef RLIMIT_MEMLOCK
walid-git marked this conversation as resolved.
Show resolved Hide resolved
static void
printlim(const char *name, rlim_t lim)
{

fprintf(stderr, "Info: %s: ", name);
if (lim == RLIM_INFINITY)
fprintf(stderr, "unlimited\n");
else
fprintf(stderr, "%ju bytes\n", (uintmax_t)lim);
}

static void
printmemlock(void) {
struct rlimit rlim;

AZ(getrlimit(RLIMIT_MEMLOCK, &rlim));
printlim("max locked memory (soft)", rlim.rlim_cur);
printlim("max locked memory (hard)", rlim.rlim_max);
}
#else
static void printmemlock(void) {}
#endif

static struct vsmw_cluster *
vsmw_newcluster(struct vsmw *vsmw, size_t len, const char *pfx)
{
Expand Down Expand Up @@ -311,6 +336,7 @@ vsmw_newcluster(struct vsmw *vsmw, size_t len, const char *pfx)
if (mlock(vc->ptr, len) && warn++ == 0) {
fprintf(stderr, "Warning: mlock() of VSM failed: %s (%d)\n",
VAS_errtxt(errno), errno);
printmemlock();
}

return (vc);
Expand Down
12 changes: 12 additions & 0 deletions bin/varnishd/mgt/mgt_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/socket.h>

Expand Down Expand Up @@ -873,6 +874,17 @@ main(int argc, char * const *argv)
workdir, VAS_errtxt(errno));

VJ_master(JAIL_MASTER_SYSTEM);
#ifdef RLIMIT_MEMLOCK
/* try to raise to max (ignore error), then set _cur to whatever we got */
struct rlimit rlim;
rlim.rlim_cur = 0;
rlim.rlim_max = RLIM_INFINITY;
(void)setrlimit(RLIMIT_MEMLOCK, &rlim);
AZ(getrlimit(RLIMIT_MEMLOCK, &rlim));
rlim.rlim_cur = rlim.rlim_max;
AZ(setrlimit(RLIMIT_MEMLOCK, &rlim));
#endif

AZ(system("rm -rf vmod_cache vext_cache worker_tmpdir"));
VJ_master(JAIL_MASTER_LOW);

Expand Down
6 changes: 4 additions & 2 deletions bin/varnishd/waiter/cache_waiter_epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,17 @@ vwe_thread(void *priv)
CAST_OBJ_NOTNULL(wp, ep->data.ptr, WAITED_MAGIC);
Lck_Lock(&vwe->mtx);
active = Wait_HeapDelete(w, wp);
if (active != 0) {
AN(vwe->nwaited);
vwe->nwaited--;
}
Lck_Unlock(&vwe->mtx);
if (!active) {
VSL(SLT_Debug, NO_VXID,
"epoll: spurious event (%d)", wp->fd);
continue;
}
AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_DEL, wp->fd, NULL));
AN(vwe->nwaited);
vwe->nwaited--;
if (ep->events & EPOLLIN) {
if (ep->events & EPOLLRDHUP &&
recv(wp->fd, &c, 1, MSG_PEEK) == 0)
Expand Down
46 changes: 46 additions & 0 deletions bin/varnishtest/tests/b00089.vtc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
varnishtest "connect: blackhole"

# XXX: This test case relies on a way for us to never successed in connecting
# to a backend. We need the connect syscall to hang forever. For TCP this means
# that the backend must not respond to the three-way handshake initiated by
# Varnish.
#
# One way to achieve this is to use an IP address non-routeable over the
# Internet, but this is not always a bullet-proof solution across all the
# platforms we support. Another downside with this solution is that it sends
# traffic over the local network.
#
# The current test case seems to work on a few supported platforms.
# Comment the line below to enable this test.

feature cmd false

varnish v1 -vcl {
backend default {
# Non-routeable IPv4 address to simulate connect_timeout
# XXX: $\{blackhole_backend}
.host = "10.255.255.1 80";
.max_connections = 1;
}
} -start

varnish v1 -cli "param.set connect_timeout 2"

client c1 {
txreq -url "/blackhole"
rxresp
expect resp.status == 503
} -start

client c2 {
txreq -url "/bye"
rxresp
expect resp.status == 503
} -start

client c1 -wait
client c2 -wait

varnish v1 -expect MAIN.backend_conn == 0
varnish v1 -expect MAIN.backend_busy == 1
varnish v1 -expect MAIN.backend_fail == 1
49 changes: 49 additions & 0 deletions bin/varnishtest/tests/b00090.vtc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
varnishtest "connect: blackhole with queueing"

# XXX: This test case relies on a way for us to never successed in connecting
# to a backend. We need the connect syscall to hang forever. For TCP this means
# that the backend must not respond to the three-way handshake initiated by
# Varnish.
#
# One way to achieve this is to use an IP address non-routeable over the
# Internet, but this is not always a bullet-proof solution across all the
# platforms we support. Another downside with this solution is that it sends
# traffic over the local network.
#
# The current test case seems to work on a few supported platforms.
# Comment the line below to enable this test.

feature cmd false

varnish v1 -vcl {
backend default {
# Non-routeable IPv4 address to simulate connect_timeout
# XXX: $\{blackhole_backend}
.host = "10.255.255.1 80";
.max_connections = 1;
.wait_limit = 1;
.wait_timeout = 0.2s;
}
} -start

varnish v1 -cli "param.set connect_timeout 2"

client c1 {
txreq -url "/blackhole"
rxresp
expect resp.status == 503
} -start

client c2 {
txreq -url "/bye"
rxresp
expect resp.status == 503
} -start

client c1 -wait
client c2 -wait

varnish v1 -expect MAIN.backend_conn == 0
varnish v1 -expect MAIN.backend_busy == 1
varnish v1 -expect MAIN.backend_wait_fail == 1
varnish v1 -expect MAIN.backend_fail == 1
Loading