source: bin/varnishd/cache/cache_panic.c @ 22c90f

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

Move do_gzip, do_gunzip and do_esi from worker to busyobj

  • 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/cache_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->bereq->ws != NULL)
201                pan_http("bereq", wrk->bereq, 4);
202        if (wrk->beresp->ws != NULL)
203                pan_http("beresp", wrk->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        VSB_printf(pan_vsp, "    bodystatus = %d,\n", bo->body_status);
220        VSB_printf(pan_vsp, "    },\n");
221}
222
223/*--------------------------------------------------------------------*/
224
225static void
226pan_sess(const struct sess *sp)
227{
228        const char *stp, *hand;
229
230        VSB_printf(pan_vsp, "sp = %p {\n", sp);
231        VSB_printf(pan_vsp,
232            "  fd = %d, id = %d, xid = %u,\n",
233            sp->fd, sp->vsl_id & VSL_IDENTMASK, sp->xid);
234        VSB_printf(pan_vsp, "  client = %s %s,\n",
235            sp->addr ? sp->addr : "?.?.?.?",
236            sp->port ? sp->port : "?");
237        switch (sp->step) {
238#define STEP(l, u) case STP_##u: stp = "STP_" #u; break;
239#include "tbl/steps.h"
240#undef STEP
241                default: stp = NULL;
242        }
243        hand = VCL_Return_Name(sp->handling);
244        if (stp != NULL)
245                VSB_printf(pan_vsp, "  step = %s,\n", stp);
246        else
247                VSB_printf(pan_vsp, "  step = 0x%x,\n", sp->step);
248        if (hand != NULL)
249                VSB_printf(pan_vsp, "  handling = %s,\n", hand);
250        else
251                VSB_printf(pan_vsp, "  handling = 0x%x,\n", sp->handling);
252        if (sp->err_code)
253                VSB_printf(pan_vsp,
254                    "  err_code = %d, err_reason = %s,\n", sp->err_code,
255                    sp->err_reason ? sp->err_reason : "(null)");
256
257        VSB_printf(pan_vsp, "  restarts = %d, esi_level = %d\n",
258            sp->restarts, sp->esi_level);
259
260        VSB_printf(pan_vsp, "  flags = ");
261        if (sp->wrk->do_stream) VSB_printf(pan_vsp, " do_stream");
262        if (sp->wrk->do_close)  VSB_printf(pan_vsp, " do_close");
263        VSB_printf(pan_vsp, "\n");
264        pan_busyobj(sp->wrk->busyobj);
265
266        pan_ws(sp->ws, 2);
267        pan_http("req", sp->http, 2);
268
269        if (sp->wrk != NULL)
270                pan_wrk(sp->wrk);
271
272        if (VALID_OBJ(sp->vcl, VCL_CONF_MAGIC))
273                pan_vcl(sp->vcl);
274
275        if (VALID_OBJ(sp->wrk->vbc, BACKEND_MAGIC))
276                pan_vbc(sp->wrk->vbc);
277
278        if (VALID_OBJ(sp->wrk->obj, OBJECT_MAGIC))
279                pan_object(sp->wrk->obj);
280
281        VSB_printf(pan_vsp, "},\n");
282}
283
284/*--------------------------------------------------------------------*/
285
286static void
287pan_backtrace(void)
288{
289        void *array[10];
290        size_t size;
291        size_t i;
292
293        size = backtrace (array, 10);
294        if (size == 0)
295                return;
296        VSB_printf(pan_vsp, "Backtrace:\n");
297        for (i = 0; i < size; i++) {
298                VSB_printf (pan_vsp, "  ");
299                if (Symbol_Lookup(pan_vsp, array[i]) < 0) {
300                        char **strings;
301                        strings = backtrace_symbols(&array[i], 1);
302                        if (strings != NULL && strings[0] != NULL)
303                                VSB_printf(pan_vsp,
304                                     "%p: %s", array[i], strings[0]);
305                        else
306                                VSB_printf(pan_vsp, "%p: (?)", array[i]);
307                }
308                VSB_printf (pan_vsp, "\n");
309        }
310}
311
312/*--------------------------------------------------------------------*/
313
314static void
315pan_ic(const char *func, const char *file, int line, const char *cond,
316    int err, int xxx)
317{
318        const char *q;
319        const struct sess *sp;
320
321        AZ(pthread_mutex_lock(&panicstr_mtx)); /* Won't be released,
322                                                  we're going to die
323                                                  anyway */
324        switch(xxx) {
325        case 3:
326                VSB_printf(pan_vsp,
327                    "Wrong turn at %s:%d:\n%s\n", file, line, cond);
328                break;
329        case 2:
330                VSB_printf(pan_vsp,
331                    "Panic from VCL:\n  %s\n", cond);
332                break;
333        case 1:
334                VSB_printf(pan_vsp,
335                    "Missing errorhandling code in %s(), %s line %d:\n"
336                    "  Condition(%s) not true.",
337                    func, file, line, cond);
338                break;
339        default:
340        case 0:
341                VSB_printf(pan_vsp,
342                    "Assert error in %s(), %s line %d:\n"
343                    "  Condition(%s) not true.\n",
344                    func, file, line, cond);
345                break;
346        }
347        if (err)
348                VSB_printf(pan_vsp, "errno = %d (%s)\n", err, strerror(err));
349
350        q = THR_GetName();
351        if (q != NULL)
352                VSB_printf(pan_vsp, "thread = (%s)\n", q);
353
354        VSB_printf(pan_vsp, "ident = %s,%s\n",
355            VSB_data(vident) + 1, WAIT_GetName());
356
357        pan_backtrace();
358
359        if (!(cache_param->diag_bitmap & 0x2000)) {
360                sp = THR_GetSession();
361                if (sp != NULL)
362                        pan_sess(sp);
363        }
364        VSB_printf(pan_vsp, "\n");
365        VSB_bcat(pan_vsp, "", 1);       /* NUL termination */
366
367        if (cache_param->diag_bitmap & 0x4000)
368                (void)fputs(heritage.panic_str, stderr);
369
370        if (cache_param->diag_bitmap & 0x1000)
371                exit(4);
372        else
373                abort();
374}
375
376/*--------------------------------------------------------------------*/
377
378void
379PAN_Init(void)
380{
381
382        VAS_Fail = pan_ic;
383        pan_vsp = &pan_vsp_storage;
384        AN(heritage.panic_str);
385        AN(heritage.panic_str_len);
386        AN(VSB_new(pan_vsp, heritage.panic_str, heritage.panic_str_len,
387            VSB_FIXEDLEN));
388}
Note: See TracBrowser for help on using the repository browser.