source: bin/varnishd/cache/cache_panic.c @ 9173a98

Revision 9173a98, 10.2 KB checked in by Poul-Henning Kamp <phk@…>, 2 years ago (diff)

Move xid from sess to req

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2011 Varnish Software AS
4 * All rights reserved.
5 *
6 * Author: Dag-Erling Smørgrav <des@des.no>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include "config.h"
31
32#ifndef HAVE_EXECINFO_H
33#include "compat/execinfo.h"
34#else
35#include <execinfo.h>
36#endif
37
38#include <stdio.h>
39#include <stdlib.h>
40
41#include "cache.h"
42#include "common/heritage.h"
43
44#include "cache_backend.h"
45#include "waiter/waiter.h"
46#include "vcl.h"
47
48/*
49 * The panic string is constructed in memory, then copied to the
50 * shared memory.
51 *
52 * It can be extracted post-mortem from a core dump using gdb:
53 *
54 * (gdb) printf "%s", panicstr
55 */
56
57static struct vsb pan_vsp_storage, *pan_vsp;
58static pthread_mutex_t panicstr_mtx = PTHREAD_MUTEX_INITIALIZER;
59
60/*--------------------------------------------------------------------*/
61
62static void
63pan_ws(const struct ws *ws, int indent)
64{
65
66        VSB_printf(pan_vsp, "%*sws = %p { %s\n", indent, "",
67            ws, ws->overflow ? "overflow" : "");
68        VSB_printf(pan_vsp, "%*sid = \"%s\",\n", indent + 2, "", ws->id);
69        VSB_printf(pan_vsp, "%*s{s,f,r,e} = {%p", indent + 2, "", ws->s);
70        if (ws->f > ws->s)
71                VSB_printf(pan_vsp, ",+%ld", (long) (ws->f - ws->s));
72        else
73                VSB_printf(pan_vsp, ",%p", ws->f);
74        if (ws->r > ws->s)
75                VSB_printf(pan_vsp, ",+%ld", (long) (ws->r - ws->s));
76        else
77                VSB_printf(pan_vsp, ",%p", ws->r);
78        if (ws->e > ws->s)
79                VSB_printf(pan_vsp, ",+%ld", (long) (ws->e - ws->s));
80        else
81                VSB_printf(pan_vsp, ",%p", ws->e);
82        VSB_printf(pan_vsp, "},\n");
83        VSB_printf(pan_vsp, "%*s},\n", indent, "" );
84}
85
86/*--------------------------------------------------------------------*/
87
88static void
89pan_vbc(const struct vbc *vbc)
90{
91
92        struct backend *be;
93
94        be = vbc->backend;
95
96        VSB_printf(pan_vsp, "  backend = %p fd = %d {\n", be, vbc->fd);
97        VSB_printf(pan_vsp, "    display_name = \"%s\",\n", be->display_name);
98        VSB_printf(pan_vsp, "  },\n");
99}
100
101/*--------------------------------------------------------------------*/
102
103static void
104pan_storage(const struct storage *st)
105{
106        int i, j;
107
108#define MAX_BYTES (4*16)
109#define show(ch) (((ch) > 31 && (ch) < 127) ? (ch) : '.')
110
111        VSB_printf(pan_vsp, "      %u {\n", st->len);
112        for (i = 0; i < MAX_BYTES && i < st->len; i += 16) {
113                VSB_printf(pan_vsp, "        ");
114                for (j = 0; j < 16; ++j) {
115                        if (i + j < st->len)
116                                VSB_printf(pan_vsp, "%02x ", st->ptr[i + j]);
117                        else
118                                VSB_printf(pan_vsp, "   ");
119                }
120                VSB_printf(pan_vsp, "|");
121                for (j = 0; j < 16; ++j)
122                        if (i + j < st->len)
123                                VSB_printf(pan_vsp,
124                                    "%c", show(st->ptr[i + j]));
125                VSB_printf(pan_vsp, "|\n");
126        }
127        if (st->len > MAX_BYTES)
128                VSB_printf(pan_vsp,
129                    "        [%u more]\n", st->len - MAX_BYTES);
130        VSB_printf(pan_vsp, "      },\n");
131
132#undef show
133#undef MAX_BYTES
134}
135
136/*--------------------------------------------------------------------*/
137
138static void
139pan_http(const char *id, const struct http *h, int indent)
140{
141        int i;
142
143        VSB_printf(pan_vsp, "%*shttp[%s] = {\n", indent, "", id);
144        VSB_printf(pan_vsp, "%*sws = %p[%s]\n", indent + 2, "",
145            h->ws, h->ws ? h->ws->id : "");
146        for (i = 0; i < h->nhd; ++i) {
147                if (h->hd[i].b == NULL && h->hd[i].e == NULL)
148                        continue;
149                VSB_printf(pan_vsp, "%*s\"%.*s\",\n", indent + 4, "",
150                    (int)(h->hd[i].e - h->hd[i].b),
151                    h->hd[i].b);
152        }
153        VSB_printf(pan_vsp, "%*s},\n", indent, "");
154}
155
156
157/*--------------------------------------------------------------------*/
158
159static void
160pan_object(const struct object *o)
161{
162        const struct storage *st;
163
164        VSB_printf(pan_vsp, "  obj = %p {\n", o);
165        VSB_printf(pan_vsp, "    xid = %u,\n", o->xid);
166        pan_ws(o->ws_o, 4);
167        pan_http("obj", o->http, 4);
168        VSB_printf(pan_vsp, "    len = %jd,\n", (intmax_t)o->len);
169        VSB_printf(pan_vsp, "    store = {\n");
170        VTAILQ_FOREACH(st, &o->store, list)
171                pan_storage(st);
172        VSB_printf(pan_vsp, "    },\n");
173        VSB_printf(pan_vsp, "  },\n");
174}
175
176/*--------------------------------------------------------------------*/
177
178static void
179pan_vcl(const struct VCL_conf *vcl)
180{
181        int i;
182
183        VSB_printf(pan_vsp, "    vcl = {\n");
184        VSB_printf(pan_vsp, "      srcname = {\n");
185        for (i = 0; i < vcl->nsrc; ++i)
186                VSB_printf(pan_vsp, "        \"%s\",\n", vcl->srcname[i]);
187        VSB_printf(pan_vsp, "      },\n");
188        VSB_printf(pan_vsp, "    },\n");
189}
190
191
192/*--------------------------------------------------------------------*/
193
194static void
195pan_wrk(const struct worker *wrk)
196{
197
198        VSB_printf(pan_vsp, "  worker = %p {\n", wrk);
199        pan_ws(wrk->ws, 4);
200        if (wrk->busyobj != NULL && wrk->busyobj->bereq->ws != NULL)
201                pan_http("bereq", wrk->busyobj->bereq, 4);
202        if (wrk->busyobj != NULL && wrk->busyobj->beresp->ws != NULL)
203                pan_http("beresp", wrk->busyobj->beresp, 4);
204        if (wrk->resp->ws != NULL)
205                pan_http("resp", wrk->resp, 4);
206        VSB_printf(pan_vsp, "  },\n");
207}
208
209static void
210pan_busyobj(const struct busyobj *bo)
211{
212
213        VSB_printf(pan_vsp, "  busyobj = %p {\n", bo);
214        if (bo->is_gzip)        VSB_printf(pan_vsp, "    is_gzip\n");
215        if (bo->is_gunzip)      VSB_printf(pan_vsp, "    is_gunzip\n");
216        if (bo->do_gzip)        VSB_printf(pan_vsp, "    do_gzip\n");
217        if (bo->do_gunzip)      VSB_printf(pan_vsp, "    do_gunzip\n");
218        if (bo->do_esi)         VSB_printf(pan_vsp, "    do_esi\n");
219        if (bo->do_stream)      VSB_printf(pan_vsp, "    do_stream\n");
220        if (bo->should_close)   VSB_printf(pan_vsp, "    should_close\n");
221        VSB_printf(pan_vsp, "    bodystatus = %d,\n", bo->body_status);
222        VSB_printf(pan_vsp, "    },\n");
223        if (VALID_OBJ(bo->vbc, BACKEND_MAGIC))
224                pan_vbc(bo->vbc);
225
226}
227
228/*--------------------------------------------------------------------*/
229
230static void
231pan_sess(const struct sess *sp)
232{
233        const char *stp, *hand;
234
235        VSB_printf(pan_vsp, "sp = %p {\n", sp);
236        VSB_printf(pan_vsp,
237            "  fd = %d, id = %u, xid = %u,\n",
238            sp->fd, sp->vsl_id & VSL_IDENTMASK, sp->req->xid);
239        VSB_printf(pan_vsp, "  client = %s %s,\n",
240            sp->addr ? sp->addr : "?.?.?.?",
241            sp->port ? sp->port : "?");
242        switch (sp->step) {
243#define STEP(l, u) case STP_##u: stp = "STP_" #u; break;
244#include "tbl/steps.h"
245#undef STEP
246                default: stp = NULL;
247        }
248        hand = VCL_Return_Name(sp->handling);
249        if (stp != NULL)
250                VSB_printf(pan_vsp, "  step = %s,\n", stp);
251        else
252                VSB_printf(pan_vsp, "  step = 0x%x,\n", sp->step);
253        if (hand != NULL)
254                VSB_printf(pan_vsp, "  handling = %s,\n", hand);
255        else
256                VSB_printf(pan_vsp, "  handling = 0x%x,\n", sp->handling);
257        if (sp->err_code)
258                VSB_printf(pan_vsp,
259                    "  err_code = %d, err_reason = %s,\n", sp->err_code,
260                    sp->err_reason ? sp->err_reason : "(null)");
261
262        VSB_printf(pan_vsp, "  restarts = %d, esi_level = %d\n",
263            sp->restarts, sp->esi_level);
264
265        if (sp->wrk->busyobj != NULL)
266                pan_busyobj(sp->wrk->busyobj);
267
268        pan_ws(sp->ws, 2);
269        pan_http("req", sp->http, 2);
270
271        if (sp->wrk != NULL)
272                pan_wrk(sp->wrk);
273
274        if (VALID_OBJ(sp->vcl, VCL_CONF_MAGIC))
275                pan_vcl(sp->vcl);
276
277        if (VALID_OBJ(sp->wrk->obj, OBJECT_MAGIC))
278                pan_object(sp->wrk->obj);
279
280        VSB_printf(pan_vsp, "},\n");
281}
282
283/*--------------------------------------------------------------------*/
284
285static void
286pan_backtrace(void)
287{
288        void *array[10];
289        size_t size;
290        size_t i;
291
292        size = backtrace (array, 10);
293        if (size == 0)
294                return;
295        VSB_printf(pan_vsp, "Backtrace:\n");
296        for (i = 0; i < size; i++) {
297                VSB_printf (pan_vsp, "  ");
298                if (Symbol_Lookup(pan_vsp, array[i]) < 0) {
299                        char **strings;
300                        strings = backtrace_symbols(&array[i], 1);
301                        if (strings != NULL && strings[0] != NULL)
302                                VSB_printf(pan_vsp,
303                                     "%p: %s", array[i], strings[0]);
304                        else
305                                VSB_printf(pan_vsp, "%p: (?)", array[i]);
306                }
307                VSB_printf (pan_vsp, "\n");
308        }
309}
310
311/*--------------------------------------------------------------------*/
312
313static void
314pan_ic(const char *func, const char *file, int line, const char *cond,
315    int err, int xxx)
316{
317        const char *q;
318        const struct sess *sp;
319
320        AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released,
321                                                  we're going to die
322                                                  anyway */
323        switch(xxx) {
324        case 3:
325                VSB_printf(pan_vsp,
326                    "Wrong turn at %s:%d:\n%s\n", file, line, cond);
327                break;
328        case 2:
329                VSB_printf(pan_vsp,
330                    "Panic from VCL:\n  %s\n", cond);
331                break;
332        case 1:
333                VSB_printf(pan_vsp,
334                    "Missing errorhandling code in %s(), %s line %d:\n"
335                    "  Condition(%s) not true.",
336                    func, file, line, cond);
337                break;
338        default:
339        case 0:
340                VSB_printf(pan_vsp,
341                    "Assert error in %s(), %s line %d:\n"
342                    "  Condition(%s) not true.\n",
343                    func, file, line, cond);
344                break;
345        }
346        if (err)
347                VSB_printf(pan_vsp, "errno = %d (%s)\n", err, strerror(err));
348
349        q = THR_GetName();
350        if (q != NULL)
351                VSB_printf(pan_vsp, "thread = (%s)\n", q);
352
353        VSB_printf(pan_vsp, "ident = %s,%s\n",
354            VSB_data(vident) + 1, WAIT_GetName());
355
356        pan_backtrace();
357
358        if (!(cache_param->diag_bitmap & 0x2000)) {
359                sp = THR_GetSession();
360                if (sp != NULL)
361                        pan_sess(sp);
362        }
363        VSB_printf(pan_vsp, "\n");
364        VSB_bcat(pan_vsp, "", 1);       /* NUL termination */
365
366        if (cache_param->diag_bitmap & 0x4000)
367                (void)fputs(heritage.panic_str, stderr);
368
369        if (cache_param->diag_bitmap & 0x1000)
370                exit(4);
371        else
372                abort();
373}
374
375/*--------------------------------------------------------------------*/
376
377void
378PAN_Init(void)
379{
380
381        VAS_Fail = pan_ic;
382        pan_vsp = &pan_vsp_storage;
383        AN(heritage.panic_str);
384        AN(heritage.panic_str_len);
385        AN(VSB_new(pan_vsp, heritage.panic_str, heritage.panic_str_len,
386            VSB_FIXEDLEN));
387}
Note: See TracBrowser for help on using the repository browser.