[master] ce3e446f4 varnishtest: make varnish fatal error wait for output
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Wed Jul 3 09:33:05 UTC 2024
commit ce3e446f4e088059ee6e532758da3f6e10501b3d
Author: Stephane Cance <stephane.cance at varnish-software.com>
Date: Thu May 2 13:33:37 2024 +0200
varnishtest: make varnish fatal error wait for output
diff --git a/bin/varnishtest/vtc_varnish.c b/bin/varnishtest/vtc_varnish.c
index 0564ec61a..d72242196 100644
--- a/bin/varnishtest/vtc_varnish.c
+++ b/bin/varnishtest/vtc_varnish.c
@@ -97,6 +97,45 @@ struct varnish {
static VTAILQ_HEAD(, varnish) varnishes =
VTAILQ_HEAD_INITIALIZER(varnishes);
+/**********************************************************************
+ * Fatal condition cleanup
+ * Invalid to call in any code path not followed by vtc_fatal().
+ */
+
+static void
+varnish_fatal_cleanup(const struct varnish *v)
+{
+ struct pollfd fd[1];
+ int n;
+
+ if (!pthread_equal(pthread_self(), vtc_thread))
+ return;
+
+ if (!v->tp_started)
+ return;
+
+ memset(fd, 0, sizeof(fd));
+ fd[0].fd = v->fds[0];
+ fd[0].events = POLLIN;
+
+ do {
+ n = poll(fd, sizeof(fd)/sizeof(fd[0]), 10);
+ if (n == 1 && (fd[0].revents & (POLLHUP|POLLERR)) != 0) {
+ PTOK(pthread_join(v->tp, NULL));
+ break;
+ }
+
+ if (n == 1)
+ usleep(10000);
+ } while (n > 0);
+}
+
+#define varnish_fatal(v, ...) \
+ do { \
+ varnish_fatal_cleanup((v)); \
+ vtc_fatal((v)->vl, __VA_ARGS__); \
+ } while (0)
+
/**********************************************************************
* Ask a question over CLI
*/
@@ -112,16 +151,16 @@ varnish_ask_cli(const struct varnish *v, const char *cmd, char **repl)
vtc_dump(v->vl, 4, "CLI TX", cmd, -1);
i = write(v->cli_fd, cmd, strlen(cmd));
if (i != strlen(cmd) && !vtc_stop)
- vtc_fatal(v->vl, "CLI write failed (%s) = %u %s",
+ varnish_fatal(v, "CLI write failed (%s) = %u %s",
cmd, errno, strerror(errno));
i = write(v->cli_fd, "\n", 1);
if (i != 1 && !vtc_stop)
- vtc_fatal(v->vl, "CLI write failed (%s) = %u %s",
+ varnish_fatal(v, "CLI write failed (%s) = %u %s",
cmd, errno, strerror(errno));
}
i = VCLI_ReadResult(v->cli_fd, &retval, &r, vtc_maxdur);
if (i != 0 && !vtc_stop)
- vtc_fatal(v->vl, "CLI failed (%s) = %d %u %s",
+ varnish_fatal(v, "CLI failed (%s) = %d %u %s",
cmd != NULL ? cmd : "NULL", i, retval, r);
vtc_log(v->vl, 3, "CLI RX %u", retval);
vtc_dump(v->vl, 4, "CLI RX", r, -1);
@@ -146,7 +185,7 @@ wait_stopped(const struct varnish *v)
while (1) {
st = varnish_ask_cli(v, "status", &r);
if (st != CLIS_OK)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"CLI status command failed: %u %s", st, r);
if (!strcmp(r, "Child in state stopped")) {
free(r);
@@ -171,17 +210,17 @@ wait_running(const struct varnish *v)
vtc_log(v->vl, 3, "wait-running");
st = varnish_ask_cli(v, "status", &r);
if (st != CLIS_OK)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"CLI status command failed: %u %s", st, r);
if (!strcmp(r, "Child in state stopped"))
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"Child stopped before running: %u %s", st, r);
if (!strcmp(r, "Child in state running")) {
free(r);
r = NULL;
st = varnish_ask_cli(v, "debug.listen_address", &r);
if (st != CLIS_OK)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"CLI status command failed: %u %s", st, r);
free(r);
break;
@@ -399,7 +438,7 @@ varnish_launch(struct varnish *v)
/* Create listener socket */
asock = VTCP_listen_on(default_listen_addr, NULL, 1, &err);
if (err != NULL)
- vtc_fatal(v->vl, "Create CLI listen socket failed: %s", err);
+ varnish_fatal(v, "Create CLI listen socket failed: %s", err);
assert(asock > 0);
VTCP_myname(asock, abuf, sizeof abuf, pbuf, sizeof pbuf);
@@ -490,15 +529,15 @@ varnish_launch(struct varnish *v)
vtc_log(v->vl, 4, "CLIPOLL %d 0x%x 0x%x 0x%x",
i, fd[0].revents, fd[1].revents, fd[2].revents);
if (i == 0)
- vtc_fatal(v->vl, "FAIL timeout waiting for CLI connection");
+ varnish_fatal(v, "FAIL timeout waiting for CLI connection");
if (fd[1].revents & POLLHUP)
- vtc_fatal(v->vl, "FAIL debug pipe closed");
+ varnish_fatal(v, "FAIL debug pipe closed");
if (!(fd[0].revents & POLLIN))
- vtc_fatal(v->vl, "FAIL CLI connection wait failure");
+ varnish_fatal(v, "FAIL CLI connection wait failure");
nfd = accept(asock, NULL, NULL);
closefd(&asock);
if (nfd < 0)
- vtc_fatal(v->vl, "FAIL no CLI connection accepted");
+ varnish_fatal(v, "FAIL no CLI connection accepted");
v->cli_fd = nfd;
@@ -510,7 +549,7 @@ varnish_launch(struct varnish *v)
if (vtc_error)
return;
if (u != CLIS_AUTH)
- vtc_fatal(v->vl, "CLI auth demand expected: %u %s", u, r);
+ varnish_fatal(v, "CLI auth demand expected: %u %s", u, r);
bprintf(lbuf, "%s/_.secret", v->workdir);
nfd = open(lbuf, O_RDONLY);
@@ -528,7 +567,7 @@ varnish_launch(struct varnish *v)
if (vtc_error)
return;
if (u != CLIS_OK)
- vtc_fatal(v->vl, "CLI auth command failed: %u %s", u, r);
+ varnish_fatal(v, "CLI auth command failed: %u %s", u, r);
free(r);
v->vsm_vsc = VSM_New();
@@ -630,7 +669,7 @@ varnish_start(struct varnish *v)
if (vtc_error)
return;
if (u != CLIS_OK)
- vtc_fatal(v->vl, "CLI start command failed: %u %s", u, resp);
+ varnish_fatal(v, "CLI start command failed: %u %s", u, resp);
wait_running(v);
free(resp);
resp = NULL;
@@ -638,7 +677,7 @@ varnish_start(struct varnish *v)
if (vtc_error)
return;
if (u != CLIS_OK)
- vtc_fatal(v->vl, "CLI debug.xid command failed: %u %s",
+ varnish_fatal(v, "CLI debug.xid command failed: %u %s",
u, resp);
free(resp);
resp = NULL;
@@ -646,7 +685,7 @@ varnish_start(struct varnish *v)
if (vtc_error)
return;
if (u != CLIS_OK)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"CLI debug.listen_address command failed: %u %s", u, resp);
varnish_listen(v, resp);
free(resp);
@@ -718,7 +757,7 @@ varnish_wait(struct varnish *v)
varnish_stop(v);
if (varnish_ask_cli(v, "panic.show", NULL) != CLIS_CANT)
- vtc_fatal(v->vl, "Unexpected panic");
+ varnish_fatal(v, "Unexpected panic");
varnish_cleanup(v);
}
@@ -740,11 +779,11 @@ varnish_cli_json(struct varnish *v, const char *cli)
u = varnish_ask_cli(v, cli, &resp);
vtc_log(v->vl, 2, "CLI %03u <%s>", u, cli);
if (u != CLIS_OK)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"FAIL CLI response %u expected %u", u, CLIS_OK);
vj = vjsn_parse(resp, &errptr);
if (vj == NULL)
- vtc_fatal(v->vl, "FAIL CLI, not good JSON: %s", errptr);
+ varnish_fatal(v, "FAIL CLI, not good JSON: %s", errptr);
vjsn_delete(&vj);
free(resp);
}
@@ -770,14 +809,14 @@ varnish_cli(struct varnish *v, const char *cli, unsigned exp, const char *re)
AZ(VRE_error(vsb, err));
AZ(VSB_finish(vsb));
VSB_fini(vsb);
- vtc_fatal(v->vl, "Illegal regexp: %s (@%d)",
+ varnish_fatal(v, "Illegal regexp: %s (@%d)",
errbuf, erroff);
}
}
u = varnish_ask_cli(v, cli, &resp);
vtc_log(v->vl, 2, "CLI %03u <%s>", u, cli);
if (exp != 0 && exp != (unsigned)u)
- vtc_fatal(v->vl, "FAIL CLI response %u expected %u", u, exp);
+ varnish_fatal(v, "FAIL CLI response %u expected %u", u, exp);
if (vre != NULL) {
err = VRE_match(vre, resp, 0, 0, NULL);
if (err < 1) {
@@ -785,7 +824,7 @@ varnish_cli(struct varnish *v, const char *cli, unsigned exp, const char *re)
AZ(VRE_error(vsb, err));
AZ(VSB_finish(vsb));
VSB_fini(vsb);
- vtc_fatal(v->vl, "Expect failed (%s)", errbuf);
+ varnish_fatal(v, "Expect failed (%s)", errbuf);
}
VRE_free(&vre);
}
@@ -819,10 +858,10 @@ varnish_vcl(struct varnish *v, const char *vcl, int fail, char **resp)
}
if (u == CLIS_OK && fail) {
VSB_destroy(&vsb);
- vtc_fatal(v->vl, "VCL compilation succeeded expected failure");
+ varnish_fatal(v, "VCL compilation succeeded expected failure");
} else if (u != CLIS_OK && !fail) {
VSB_destroy(&vsb);
- vtc_fatal(v->vl, "VCL compilation failed expected success");
+ varnish_fatal(v, "VCL compilation failed expected success");
} else if (fail)
vtc_log(v->vl, 2, "VCL compilation failed (as expected)");
VSB_destroy(&vsb);
@@ -859,7 +898,7 @@ varnish_vclbackend(struct varnish *v, const char *vcl)
if (u != CLIS_OK) {
VSB_destroy(&vsb);
VSB_destroy(&vsb2);
- vtc_fatal(v->vl, "FAIL VCL does not compile");
+ varnish_fatal(v, "FAIL VCL does not compile");
}
VSB_clear(vsb);
VSB_printf(vsb, "vcl.use vcl%d", v->vcl_nbr);
@@ -1011,7 +1050,7 @@ varnish_expect(struct varnish *v, char * const *av)
continue;
if (not)
- vtc_fatal(v->vl, "Found (not expected): %s", l);
+ varnish_fatal(v, "Found (not expected): %s", l);
good = -1;
if (!strcmp(av[1], "==")) good = (sp.lhs.val == sp.rhs.val);
@@ -1021,19 +1060,19 @@ varnish_expect(struct varnish *v, char * const *av)
if (!strcmp(av[1], ">=")) good = (sp.lhs.val >= sp.rhs.val);
if (!strcmp(av[1], "<=")) good = (sp.lhs.val <= sp.rhs.val);
if (good == -1)
- vtc_fatal(v->vl, "comparison %s unknown", av[1]);
+ varnish_fatal(v, "comparison %s unknown", av[1]);
if (good)
break;
}
if (good == -1) {
- vtc_fatal(v->vl, "VSM error: %s", VSM_Error(v->vsm_vsc));
+ varnish_fatal(v, "VSM error: %s", VSM_Error(v->vsm_vsc));
}
if (good == -2) {
if (not) {
vtc_log(v->vl, 2, "not found (as expected): %s", l);
return;
}
- vtc_fatal(v->vl, "stats field %s unknown",
+ varnish_fatal(v, "stats field %s unknown",
sp.lhs.good ? sp.rhs.pattern : sp.lhs.pattern);
}
@@ -1041,7 +1080,7 @@ varnish_expect(struct varnish *v, char * const *av)
vtc_log(v->vl, 2, "as expected: %s (%ju) %s %s (%ju)",
av[0], sp.lhs.val, av[1], av[2], sp.rhs.val);
} else {
- vtc_fatal(v->vl, "Not true: %s (%ju) %s %s (%ju)",
+ varnish_fatal(v, "Not true: %s (%ju) %s %s (%ju)",
av[0], sp.lhs.val, av[1], av[2], sp.rhs.val);
}
}
@@ -1272,7 +1311,7 @@ cmd_varnish(CMD_ARGS)
AN(av[2]);
varnish_vcl(v, av[2], 1, &r);
if (strstr(r, av[1]) == NULL)
- vtc_fatal(v->vl,
+ varnish_fatal(v,
"Did not find expected string: (\"%s\")",
av[1]);
else
@@ -1356,7 +1395,7 @@ cmd_varnish(CMD_ARGS)
vsl_catchup(v);
continue;
}
- vtc_fatal(v->vl, "Unknown varnish argument: %s", *av);
+ varnish_fatal(v, "Unknown varnish argument: %s", *av);
}
}
More information about the varnish-commit
mailing list