Commit 6e79b313 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Reconstitute the dumping of sessions, objects &c &c, but now do it for

all asserts from a thread with a registered session.



git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@2975 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent b948debd
...@@ -37,211 +37,198 @@ ...@@ -37,211 +37,198 @@
#include <stdlib.h> #include <stdlib.h>
#include "cache.h" #include "cache.h"
#include "cache_backend.h"
#include "vcl.h" #include "vcl.h"
#ifndef WITHOUT_ASSERTS
/* /*
* The panic string is constructed in memory, then printed to stderr. It * The panic string is constructed in memory, then copied to the
* can be extracted post-mortem from a core dump using gdb: * shared memory.
*
* It can be extracted post-mortem from a core dump using gdb:
* *
* (gdb) printf "%s", panicstr * (gdb) printf "%s", panicstr
*/ */
char panicstr[65536]; char panicstr[65536];
static struct vsb vsps, *vsp; static struct vsb vsps, *vsp;
static char *pstr = panicstr; #if 0
#define fp(...) \ void
do { \ panic(const char *file, int line, const char *func,
pstr += snprintf(pstr, \ const struct sess *sp, const char *fmt, ...)
(panicstr + sizeof panicstr) - pstr, \ {
__VA_ARGS__); \ va_list ap;
} while (0)
vsb_printf(vsp, "panic in %s() at %s:%d\n", func, file, line);
#define vfp(fmt, ap) \ va_start(ap, fmt);
do { \ vvsb_printf(vsp, fmt, ap);
pstr += vsnprintf(pstr, \ va_end(ap);
(panicstr + sizeof panicstr) - pstr, \
(fmt), (ap)); \ if (VALID_OBJ(sp, SESS_MAGIC))
} while (0) dump_sess(sp);
/* step names */ (void)fputs(panicstr, stderr);
static const char *steps[] = {
#define STEP(l, u) [STP_##u] = "STP_" #u, /* I wish there was a way to flush the log buffers... */
#include "steps.h" (void)signal(SIGABRT, SIG_DFL);
#undef STEP #ifdef HAVE_ABORT2
}; {
static int nsteps = sizeof steps / sizeof *steps; void *arg[1];
char *p;
for (p = panicstr; *p; p++)
if (*p == '\n')
*p = ' ';
arg[0] = panicstr;
abort2(panicstr, 1, arg);
}
#endif
(void)raise(SIGABRT);
}
#endif
/*--------------------------------------------------------------------*/
/* dump a struct VCL_conf */
static void static void
dump_vcl(const struct VCL_conf *vcl) pan_backend(const struct backend *be)
{ {
int i;
fp(" vcl = {\n"); vsb_printf(vsp, " backend = %p {\n", be);
fp(" srcname = {\n"); vsb_printf(vsp, " vcl_name = \"%s\",\n", be->vcl_name);
for (i = 0; i < vcl->nsrc; ++i) vsb_printf(vsp, " },\n");
fp(" \"%s\",\n", vcl->srcname[i]);
fp(" },\n");
fp(" },\n");
} }
/* dump a struct storage */ /*--------------------------------------------------------------------*/
static void static void
dump_storage(const struct storage *st) pan_storage(const struct storage *st)
{ {
int i, j; int i, j;
#define MAX_BYTES (4*16) #define MAX_BYTES (4*16)
#define show(ch) (((ch) > 31 && (ch) < 127) ? (ch) : '.') #define show(ch) (((ch) > 31 && (ch) < 127) ? (ch) : '.')
fp(" %u {\n", st->len); vsb_printf(vsp, " %u {\n", st->len);
for (i = 0; i < MAX_BYTES && i < st->len; i += 16) { for (i = 0; i < MAX_BYTES && i < st->len; i += 16) {
fp(" "); vsb_printf(vsp, " ");
for (j = 0; j < 16; ++j) { for (j = 0; j < 16; ++j) {
if (i + j < st->len) if (i + j < st->len)
fp("%02x ", st->ptr[i + j]); vsb_printf(vsp, "%02x ", st->ptr[i + j]);
else else
fp(" "); vsb_printf(vsp, " ");
} }
fp("|"); vsb_printf(vsp, "|");
for (j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
if (i + j < st->len) if (i + j < st->len)
fp("%c", show(st->ptr[i + j])); vsb_printf(vsp, "%c", show(st->ptr[i + j]));
fp("|\n"); vsb_printf(vsp, "|\n");
} }
if (st->len > MAX_BYTES) if (st->len > MAX_BYTES)
fp(" [%u more]\n", st->len - MAX_BYTES); vsb_printf(vsp, " [%u more]\n", st->len - MAX_BYTES);
fp(" },\n"); vsb_printf(vsp, " },\n");
#undef show #undef show
#undef MAX_BYTES #undef MAX_BYTES
} }
/* dump a struct http */ /*--------------------------------------------------------------------*/
static void static void
dump_http(const struct http *h) pan_http(const struct http *h)
{ {
int i; int i;
fp(" http = {\n"); vsb_printf(vsp, " http = {\n");
if (h->nhd > HTTP_HDR_FIRST) { if (h->nhd > HTTP_HDR_FIRST) {
fp(" hd = {\n"); vsb_printf(vsp, " hd = {\n");
for (i = HTTP_HDR_FIRST; i < h->nhd; ++i) for (i = HTTP_HDR_FIRST; i < h->nhd; ++i)
fp(" \"%.*s\",\n", vsb_printf(vsp, " \"%.*s\",\n",
(int)(h->hd[i].e - h->hd[i].b), (int)(h->hd[i].e - h->hd[i].b),
h->hd[i].b); h->hd[i].b);
fp(" },\n"); vsb_printf(vsp, " },\n");
} }
fp(" },\n"); vsb_printf(vsp, " },\n");
} }
/* dump a struct object */
/*--------------------------------------------------------------------*/
static void static void
dump_object(const struct object *o) pan_object(const struct object *o)
{ {
const struct storage *st; const struct storage *st;
fp(" obj = %p {\n", o); vsb_printf(vsp, " obj = %p {\n", o);
fp(" refcnt = %u, xid = %u,\n", o->refcnt, o->xid); vsb_printf(vsp, " refcnt = %u, xid = %u,\n", o->refcnt, o->xid);
dump_http(o->http); pan_http(o->http);
fp(" len = %u,\n", o->len); vsb_printf(vsp, " len = %u,\n", o->len);
fp(" store = {\n"); vsb_printf(vsp, " store = {\n");
VTAILQ_FOREACH(st, &o->store, list) { VTAILQ_FOREACH(st, &o->store, list)
dump_storage(st); pan_storage(st);
} vsb_printf(vsp, " },\n");
fp(" },\n"); vsb_printf(vsp, " },\n");
fp(" },\n");
} }
#if 0 /*--------------------------------------------------------------------*/
/* dump a struct backend */
static void static void
dump_backend(const struct backend *be) pan_vcl(const struct VCL_conf *vcl)
{ {
int i;
fp(" backend = %p {\n", be); vsb_printf(vsp, " vcl = {\n");
fp(" vcl_name = \"%s\",\n", vsb_printf(vsp, " srcname = {\n");
be->vcl_name ? be->vcl_name : "(null)"); for (i = 0; i < vcl->nsrc; ++i)
fp(" },\n"); vsb_printf(vsp, " \"%s\",\n", vcl->srcname[i]);
vsb_printf(vsp, " },\n");
vsb_printf(vsp, " },\n");
} }
#endif
/* dump a struct sess */ /*--------------------------------------------------------------------*/
static void static void
dump_sess(const struct sess *sp) pan_sess(const struct sess *sp)
{ {
#if 0 const char *stp;
const struct backend *be = sp->backend;
#endif
const struct object *obj = sp->obj;
const struct VCL_conf *vcl = sp->vcl;
fp("sp = %p {\n", sp); vsb_printf(vsp, "sp = %p {\n", sp);
fp(" fd = %d, id = %d, xid = %u,\n", sp->fd, sp->id, sp->xid); vsb_printf(vsp,
fp(" client = %s:%s,\n", " fd = %d, id = %d, xid = %u,\n", sp->fd, sp->id, sp->xid);
vsb_printf(vsp, " client = %s:%s,\n",
sp->addr ? sp->addr : "?.?.?.?", sp->addr ? sp->addr : "?.?.?.?",
sp->port ? sp->port : "?"); sp->port ? sp->port : "?");
if (sp->step < nsteps) switch (sp->step) {
fp(" step = %s,\n", steps[sp->step]); /*lint -save -e525 */
#define STEP(l, u) case STP_##u: stp = "STP_" #u; break;
#include "steps.h"
#undef STEP
/*lint -restore */
default: stp = NULL;
}
if (stp != NULL)
vsb_printf(vsp, " step = %s,\n", stp);
else else
fp(" step = %d,\n", sp->step); vsb_printf(vsp, " step = 0x%x,\n", sp->step);
if (sp->err_code) if (sp->err_code)
fp(" err_code = %d, err_reason = %s,\n", sp->err_code, vsb_printf(vsp,
" err_code = %d, err_reason = %s,\n", sp->err_code,
sp->err_reason ? sp->err_reason : "(null)"); sp->err_reason ? sp->err_reason : "(null)");
if (VALID_OBJ(vcl, VCL_CONF_MAGIC)) if (VALID_OBJ(sp->vcl, VCL_CONF_MAGIC))
dump_vcl(vcl); pan_vcl(sp->vcl);
#if 0
if (VALID_OBJ(be, BACKEND_MAGIC))
dump_backend(be);
INCOMPL():
#endif
if (VALID_OBJ(obj, OBJECT_MAGIC))
dump_object(obj);
fp("},\n");
}
/* report as much information as we can before we croak */
void
panic(const char *file, int line, const char *func,
const struct sess *sp, const char *fmt, ...)
{
va_list ap;
fp("panic in %s() at %s:%d\n", func, file, line);
va_start(ap, fmt);
vfp(fmt, ap);
va_end(ap);
if (VALID_OBJ(sp, SESS_MAGIC)) if (VALID_OBJ(sp->backend, BACKEND_MAGIC))
dump_sess(sp); pan_backend(sp->backend);
(void)fputs(panicstr, stderr); if (VALID_OBJ(sp->obj, OBJECT_MAGIC))
pan_object(sp->obj);
/* I wish there was a way to flush the log buffers... */ vsb_printf(vsp, "},\n");
(void)signal(SIGABRT, SIG_DFL);
#ifdef HAVE_ABORT2
{
void *arg[1];
char *p;
for (p = panicstr; *p; p++)
if (*p == '\n')
*p = ' ';
arg[0] = panicstr;
abort2(panicstr, 1, arg);
}
#endif
(void)raise(SIGABRT);
} }
#endif /*--------------------------------------------------------------------*/
static void static void
pan_ic(const char *func, const char *file, int line, const char *cond, int err, int xxx) pan_ic(const char *func, const char *file, int line, const char *cond, int err, int xxx)
...@@ -269,16 +256,17 @@ pan_ic(const char *func, const char *file, int line, const char *cond, int err, ...@@ -269,16 +256,17 @@ pan_ic(const char *func, const char *file, int line, const char *cond, int err,
if (q != NULL) if (q != NULL)
vsb_printf(vsp, " thread = (%s)", q); vsb_printf(vsp, " thread = (%s)", q);
sp = THR_GetSession(); sp = THR_GetSession();
if (sp != NULL) if (sp != NULL)
vsb_printf(vsp, " sess = (%p)", sp); pan_sess(sp);
vsb_printf(vsp, "\n"); vsb_printf(vsp, "\n");
VSL_Panic(&l, &p); VSL_Panic(&l, &p);
if (l < vsb_len(vsp)) if (l < sizeof(panicstr))
l = vsb_len(vsp); l = sizeof(panicstr);
memcpy(p, panicstr, l); memcpy(p, panicstr, l);
abort(); abort();
} }
/*--------------------------------------------------------------------*/
void void
PAN_Init(void) PAN_Init(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment