Commit a02c92dd 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@2975 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 8e2ee17c
......@@ -37,211 +37,198 @@
#include <stdlib.h>
#include "cache.h"
#include "cache_backend.h"
#include "vcl.h"
#ifndef WITHOUT_ASSERTS
/*
* The panic string is constructed in memory, then printed to stderr. It
* can be extracted post-mortem from a core dump using gdb:
* The panic string is constructed in memory, then copied to the
* shared memory.
*
* It can be extracted post-mortem from a core dump using gdb:
*
* (gdb) printf "%s", panicstr
*/
char panicstr[65536];
static struct vsb vsps, *vsp;
static char *pstr = panicstr;
#define fp(...) \
do { \
pstr += snprintf(pstr, \
(panicstr + sizeof panicstr) - pstr, \
__VA_ARGS__); \
} while (0)
#define vfp(fmt, ap) \
do { \
pstr += vsnprintf(pstr, \
(panicstr + sizeof panicstr) - pstr, \
(fmt), (ap)); \
} while (0)
/* step names */
static const char *steps[] = {
#define STEP(l, u) [STP_##u] = "STP_" #u,
#include "steps.h"
#undef STEP
};
static int nsteps = sizeof steps / sizeof *steps;
#if 0
void
panic(const char *file, int line, const char *func,
const struct sess *sp, const char *fmt, ...)
{
va_list ap;
vsb_printf(vsp, "panic in %s() at %s:%d\n", func, file, line);
va_start(ap, fmt);
vvsb_printf(vsp, fmt, ap);
va_end(ap);
if (VALID_OBJ(sp, SESS_MAGIC))
dump_sess(sp);
(void)fputs(panicstr, stderr);
/* I wish there was a way to flush the log buffers... */
(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
/*--------------------------------------------------------------------*/
/* dump a struct VCL_conf */
static void
dump_vcl(const struct VCL_conf *vcl)
pan_backend(const struct backend *be)
{
int i;
fp(" vcl = {\n");
fp(" srcname = {\n");
for (i = 0; i < vcl->nsrc; ++i)
fp(" \"%s\",\n", vcl->srcname[i]);
fp(" },\n");
fp(" },\n");
vsb_printf(vsp, " backend = %p {\n", be);
vsb_printf(vsp, " vcl_name = \"%s\",\n", be->vcl_name);
vsb_printf(vsp, " },\n");
}
/* dump a struct storage */
/*--------------------------------------------------------------------*/
static void
dump_storage(const struct storage *st)
pan_storage(const struct storage *st)
{
int i, j;
#define MAX_BYTES (4*16)
#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) {
fp(" ");
vsb_printf(vsp, " ");
for (j = 0; j < 16; ++j) {
if (i + j < st->len)
fp("%02x ", st->ptr[i + j]);
vsb_printf(vsp, "%02x ", st->ptr[i + j]);
else
fp(" ");
vsb_printf(vsp, " ");
}
fp("|");
vsb_printf(vsp, "|");
for (j = 0; j < 16; ++j)
if (i + j < st->len)
fp("%c", show(st->ptr[i + j]));
fp("|\n");
vsb_printf(vsp, "%c", show(st->ptr[i + j]));
vsb_printf(vsp, "|\n");
}
if (st->len > MAX_BYTES)
fp(" [%u more]\n", st->len - MAX_BYTES);
fp(" },\n");
vsb_printf(vsp, " [%u more]\n", st->len - MAX_BYTES);
vsb_printf(vsp, " },\n");
#undef show
#undef MAX_BYTES
}
/* dump a struct http */
/*--------------------------------------------------------------------*/
static void
dump_http(const struct http *h)
pan_http(const struct http *h)
{
int i;
fp(" http = {\n");
vsb_printf(vsp, " http = {\n");
if (h->nhd > HTTP_HDR_FIRST) {
fp(" hd = {\n");
vsb_printf(vsp, " hd = {\n");
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),
h->hd[i].b);
fp(" },\n");
vsb_printf(vsp, " },\n");
}
fp(" },\n");
vsb_printf(vsp, " },\n");
}
/* dump a struct object */
/*--------------------------------------------------------------------*/
static void
dump_object(const struct object *o)
pan_object(const struct object *o)
{
const struct storage *st;
fp(" obj = %p {\n", o);
fp(" refcnt = %u, xid = %u,\n", o->refcnt, o->xid);
dump_http(o->http);
fp(" len = %u,\n", o->len);
fp(" store = {\n");
VTAILQ_FOREACH(st, &o->store, list) {
dump_storage(st);
}
fp(" },\n");
fp(" },\n");
vsb_printf(vsp, " obj = %p {\n", o);
vsb_printf(vsp, " refcnt = %u, xid = %u,\n", o->refcnt, o->xid);
pan_http(o->http);
vsb_printf(vsp, " len = %u,\n", o->len);
vsb_printf(vsp, " store = {\n");
VTAILQ_FOREACH(st, &o->store, list)
pan_storage(st);
vsb_printf(vsp, " },\n");
vsb_printf(vsp, " },\n");
}
#if 0
/* dump a struct backend */
/*--------------------------------------------------------------------*/
static void
dump_backend(const struct backend *be)
pan_vcl(const struct VCL_conf *vcl)
{
int i;
fp(" backend = %p {\n", be);
fp(" vcl_name = \"%s\",\n",
be->vcl_name ? be->vcl_name : "(null)");
fp(" },\n");
vsb_printf(vsp, " vcl = {\n");
vsb_printf(vsp, " srcname = {\n");
for (i = 0; i < vcl->nsrc; ++i)
vsb_printf(vsp, " \"%s\",\n", vcl->srcname[i]);
vsb_printf(vsp, " },\n");
vsb_printf(vsp, " },\n");
}
#endif
/* dump a struct sess */
/*--------------------------------------------------------------------*/
static void
dump_sess(const struct sess *sp)
pan_sess(const struct sess *sp)
{
#if 0
const struct backend *be = sp->backend;
#endif
const struct object *obj = sp->obj;
const struct VCL_conf *vcl = sp->vcl;
const char *stp;
fp("sp = %p {\n", sp);
fp(" fd = %d, id = %d, xid = %u,\n", sp->fd, sp->id, sp->xid);
fp(" client = %s:%s,\n",
vsb_printf(vsp, "sp = %p {\n", sp);
vsb_printf(vsp,
" 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->port ? sp->port : "?");
if (sp->step < nsteps)
fp(" step = %s,\n", steps[sp->step]);
switch (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
fp(" step = %d,\n", sp->step);
vsb_printf(vsp, " step = 0x%x,\n", sp->step);
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)");
if (VALID_OBJ(vcl, VCL_CONF_MAGIC))
dump_vcl(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->vcl, VCL_CONF_MAGIC))
pan_vcl(sp->vcl);
if (VALID_OBJ(sp, SESS_MAGIC))
dump_sess(sp);
if (VALID_OBJ(sp->backend, BACKEND_MAGIC))
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... */
(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);
vsb_printf(vsp, "},\n");
}
#endif
/*--------------------------------------------------------------------*/
static void
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,
if (q != NULL)
vsb_printf(vsp, " thread = (%s)", q);
sp = THR_GetSession();
if (sp != NULL)
vsb_printf(vsp, " sess = (%p)", sp);
if (sp != NULL)
pan_sess(sp);
vsb_printf(vsp, "\n");
VSL_Panic(&l, &p);
if (l < vsb_len(vsp))
l = vsb_len(vsp);
if (l < sizeof(panicstr))
l = sizeof(panicstr);
memcpy(p, panicstr, l);
abort();
}
/*--------------------------------------------------------------------*/
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