| | varnish-cache/bin/varnishd/cache/cache_main.c |
| 0 |
|
/*- |
| 1 |
|
* Copyright (c) 2006 Verdens Gang AS |
| 2 |
|
* Copyright (c) 2006-2011 Varnish Software AS |
| 3 |
|
* All rights reserved. |
| 4 |
|
* |
| 5 |
|
* Author: Poul-Henning Kamp <phk@phk.freebsd.dk> |
| 6 |
|
* |
| 7 |
|
* SPDX-License-Identifier: BSD-2-Clause |
| 8 |
|
* |
| 9 |
|
* Redistribution and use in source and binary forms, with or without |
| 10 |
|
* modification, are permitted provided that the following conditions |
| 11 |
|
* are met: |
| 12 |
|
* 1. Redistributions of source code must retain the above copyright |
| 13 |
|
* notice, this list of conditions and the following disclaimer. |
| 14 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
| 15 |
|
* notice, this list of conditions and the following disclaimer in the |
| 16 |
|
* documentation and/or other materials provided with the distribution. |
| 17 |
|
* |
| 18 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 19 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 20 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 21 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
| 22 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 23 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 24 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 25 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 26 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 27 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 28 |
|
* SUCH DAMAGE. |
| 29 |
|
*/ |
| 30 |
|
|
| 31 |
|
#include "config.h" |
| 32 |
|
|
| 33 |
|
#include "cache_varnishd.h" |
| 34 |
|
#include "acceptor/cache_acceptor.h" |
| 35 |
|
|
| 36 |
|
#include <signal.h> |
| 37 |
|
#include <stdio.h> |
| 38 |
|
#include <stdlib.h> |
| 39 |
|
|
| 40 |
|
#include <sys/mman.h> |
| 41 |
|
|
| 42 |
|
#ifdef HAVE_PTHREAD_NP_H |
| 43 |
|
# include <pthread_np.h> |
| 44 |
|
#endif |
| 45 |
|
|
| 46 |
|
#include "common/heritage.h" |
| 47 |
|
|
| 48 |
|
#include "vcli_serve.h" |
| 49 |
|
#include "vnum.h" |
| 50 |
|
#include "vtim.h" |
| 51 |
|
#include "vrnd.h" |
| 52 |
|
|
| 53 |
|
#include "hash/hash_slinger.h" |
| 54 |
|
|
| 55 |
|
volatile struct params *cache_param; |
| 56 |
|
static pthread_mutex_t cache_vrnd_mtx; |
| 57 |
|
static vtim_dur shutdown_delay = 0; |
| 58 |
|
|
| 59 |
|
pthread_mutexattr_t mtxattr_errorcheck; |
| 60 |
|
|
| 61 |
|
static void |
| 62 |
2145328 |
cache_vrnd_lock(void) |
| 63 |
|
{ |
| 64 |
2145328 |
PTOK(pthread_mutex_lock(&cache_vrnd_mtx)); |
| 65 |
2145328 |
} |
| 66 |
|
|
| 67 |
|
static void |
| 68 |
2145328 |
cache_vrnd_unlock(void) |
| 69 |
|
{ |
| 70 |
2145328 |
PTOK(pthread_mutex_unlock(&cache_vrnd_mtx)); |
| 71 |
2145328 |
} |
| 72 |
|
|
| 73 |
|
/*-------------------------------------------------------------------- |
| 74 |
|
* Per thread storage for the session currently being processed by |
| 75 |
|
* the thread. This is used for panic messages. |
| 76 |
|
*/ |
| 77 |
|
|
| 78 |
|
static pthread_key_t req_key; |
| 79 |
|
static pthread_key_t bo_key; |
| 80 |
|
static pthread_key_t wrk_key; |
| 81 |
|
pthread_key_t witness_key; |
| 82 |
|
pthread_key_t panic_key; |
| 83 |
|
|
| 84 |
|
void |
| 85 |
367213 |
THR_SetBusyobj(const struct busyobj *bo) |
| 86 |
|
{ |
| 87 |
|
|
| 88 |
367213 |
PTOK(pthread_setspecific(bo_key, bo)); |
| 89 |
367213 |
} |
| 90 |
|
|
| 91 |
|
struct busyobj * |
| 92 |
514 |
THR_GetBusyobj(void) |
| 93 |
|
{ |
| 94 |
|
|
| 95 |
514 |
return (pthread_getspecific(bo_key)); |
| 96 |
|
} |
| 97 |
|
|
| 98 |
|
void |
| 99 |
244717 |
THR_SetRequest(const struct req *req) |
| 100 |
|
{ |
| 101 |
|
|
| 102 |
244717 |
PTOK(pthread_setspecific(req_key, req)); |
| 103 |
244717 |
} |
| 104 |
|
|
| 105 |
|
struct req * |
| 106 |
594 |
THR_GetRequest(void) |
| 107 |
|
{ |
| 108 |
|
|
| 109 |
594 |
return (pthread_getspecific(req_key)); |
| 110 |
|
} |
| 111 |
|
|
| 112 |
|
void |
| 113 |
771190 |
THR_SetWorker(const struct worker *wrk) |
| 114 |
|
{ |
| 115 |
|
|
| 116 |
771190 |
PTOK(pthread_setspecific(wrk_key, wrk)); |
| 117 |
771190 |
} |
| 118 |
|
|
| 119 |
|
struct worker * |
| 120 |
173773 |
THR_GetWorker(void) |
| 121 |
|
{ |
| 122 |
|
|
| 123 |
173773 |
return (pthread_getspecific(wrk_key)); |
| 124 |
|
} |
| 125 |
|
|
| 126 |
|
/*-------------------------------------------------------------------- |
| 127 |
|
* Name threads if our pthreads implementation supports it. |
| 128 |
|
*/ |
| 129 |
|
|
| 130 |
|
static pthread_key_t name_key; |
| 131 |
|
|
| 132 |
|
#if defined(HAVE_PTHREAD_SETNAME_NP) && !defined(__APPLE__) && \ |
| 133 |
|
!defined(__NetBSD__) |
| 134 |
|
static void |
| 135 |
1377360 |
thr_setname_generic(const char *name) |
| 136 |
|
{ |
| 137 |
|
char buf[16]; |
| 138 |
|
|
| 139 |
|
/* The Linux kernel enforces a strict limitation of 15 bytes name, |
| 140 |
|
* truncate the name if we would overflow it. |
| 141 |
|
*/ |
| 142 |
1377360 |
if (strlen(name) > 15) { |
| 143 |
38034 |
bprintf(buf, "%.14s~", name); |
| 144 |
38034 |
name = buf; |
| 145 |
38034 |
} |
| 146 |
|
|
| 147 |
|
//lint --e{438} Last value assigned not used |
| 148 |
1377360 |
PTOK(pthread_setname_np(pthread_self(), name)); |
| 149 |
1377360 |
} |
| 150 |
|
#endif |
| 151 |
|
|
| 152 |
|
void |
| 153 |
1377380 |
THR_SetName(const char *name) |
| 154 |
|
{ |
| 155 |
|
|
| 156 |
1377380 |
PTOK(pthread_setspecific(name_key, name)); |
| 157 |
|
#if defined(HAVE_PTHREAD_SETNAME_NP) |
| 158 |
|
# if defined(__APPLE__) |
| 159 |
|
(void)pthread_setname_np(name); |
| 160 |
|
# elif defined(__NetBSD__) |
| 161 |
|
(void)pthread_setname_np(pthread_self(), "%s", (char *)(uintptr_t)name); |
| 162 |
|
# else |
| 163 |
1377380 |
thr_setname_generic(name); |
| 164 |
|
# endif |
| 165 |
|
#elif defined(HAVE_PTHREAD_SET_NAME_NP) |
| 166 |
|
(void)pthread_set_name_np(pthread_self(), name); |
| 167 |
|
#endif |
| 168 |
1377380 |
} |
| 169 |
|
|
| 170 |
|
const char * |
| 171 |
514 |
THR_GetName(void) |
| 172 |
|
{ |
| 173 |
|
|
| 174 |
514 |
return (pthread_getspecific(name_key)); |
| 175 |
|
} |
| 176 |
|
|
| 177 |
|
/*-------------------------------------------------------------------- |
| 178 |
|
* Generic setup all our threads should call |
| 179 |
|
*/ |
| 180 |
|
static stack_t altstack; |
| 181 |
|
|
| 182 |
|
void |
| 183 |
1377149 |
THR_Init(void) |
| 184 |
|
{ |
| 185 |
1377149 |
if (altstack.ss_sp != NULL) |
| 186 |
1375872 |
AZ(sigaltstack(&altstack, NULL)); |
| 187 |
1377149 |
} |
| 188 |
|
|
| 189 |
|
/*-------------------------------------------------------------------- |
| 190 |
|
* VXID's are unique transaction numbers allocated with a minimum of |
| 191 |
|
* locking overhead via pools in the worker threads. |
| 192 |
|
* |
| 193 |
|
* VXID's are mostly for use in VSL and for that reason we never return |
| 194 |
|
* zero vxid, in order to reserve that for "unassociated" VSL records. |
| 195 |
|
*/ |
| 196 |
|
|
| 197 |
|
static uint64_t vxid_base = 1; |
| 198 |
|
static uint32_t vxid_chunk = 32768; |
| 199 |
|
static struct lock vxid_lock; |
| 200 |
|
|
| 201 |
|
vxid_t |
| 202 |
339004 |
VXID_Get(const struct worker *wrk, uint64_t mask) |
| 203 |
|
{ |
| 204 |
|
struct vxid_pool *v; |
| 205 |
|
vxid_t retval; |
| 206 |
|
|
| 207 |
339004 |
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC); |
| 208 |
339004 |
CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC); |
| 209 |
339004 |
v = wrk->wpriv->vxid_pool; |
| 210 |
339004 |
AZ(mask & VSL_IDENTMASK); |
| 211 |
677610 |
while (v->count == 0 || v->next >= VRT_INTEGER_MAX) { |
| 212 |
338606 |
Lck_Lock(&vxid_lock); |
| 213 |
338606 |
v->next = vxid_base; |
| 214 |
338606 |
v->count = vxid_chunk; |
| 215 |
338606 |
vxid_base += v->count; |
| 216 |
338606 |
if (vxid_base >= VRT_INTEGER_MAX) |
| 217 |
80 |
vxid_base = 1; |
| 218 |
338606 |
Lck_Unlock(&vxid_lock); |
| 219 |
|
} |
| 220 |
339004 |
v->count--; |
| 221 |
339004 |
assert(v->next > 0); |
| 222 |
339004 |
assert(v->next < VSL_CLIENTMARKER); |
| 223 |
339004 |
retval.vxid = v->next | mask; |
| 224 |
339004 |
v->next++; |
| 225 |
339004 |
return (retval); |
| 226 |
|
} |
| 227 |
|
|
| 228 |
|
/*-------------------------------------------------------------------- |
| 229 |
|
* Debugging aids |
| 230 |
|
*/ |
| 231 |
|
|
| 232 |
|
/* |
| 233 |
|
* Dumb down the VXID allocation to make it predictable for |
| 234 |
|
* varnishtest cases |
| 235 |
|
*/ |
| 236 |
|
static void v_matchproto_(cli_func_t) |
| 237 |
37720 |
cli_debug_xid(struct cli *cli, const char * const *av, void *priv) |
| 238 |
|
{ |
| 239 |
37720 |
(void)priv; |
| 240 |
37720 |
if (av[2] != NULL) { |
| 241 |
37720 |
vxid_base = strtoull(av[2], NULL, 0); |
| 242 |
37720 |
vxid_chunk = 0; |
| 243 |
37720 |
if (av[3] != NULL) |
| 244 |
0 |
vxid_chunk = strtoul(av[3], NULL, 0); |
| 245 |
37720 |
if (vxid_chunk == 0) |
| 246 |
37720 |
vxid_chunk = 1; |
| 247 |
37720 |
} |
| 248 |
37720 |
VCLI_Out(cli, "XID is %ju chunk %u", (uintmax_t)vxid_base, vxid_chunk); |
| 249 |
37720 |
} |
| 250 |
|
|
| 251 |
|
/* |
| 252 |
|
* Artificially slow down the process shutdown. |
| 253 |
|
*/ |
| 254 |
|
static void v_matchproto_(cli_func_t) |
| 255 |
0 |
cli_debug_shutdown_delay(struct cli *cli, const char * const *av, void *priv) |
| 256 |
|
{ |
| 257 |
|
|
| 258 |
0 |
(void)cli; |
| 259 |
0 |
(void)priv; |
| 260 |
0 |
shutdown_delay = VNUM_duration(av[2]); |
| 261 |
0 |
} |
| 262 |
|
|
| 263 |
|
/* |
| 264 |
|
* Default to seed=1, this is the only seed value POSIX guarantees will |
| 265 |
|
* result in a reproducible random number sequence. |
| 266 |
|
*/ |
| 267 |
|
static void v_matchproto_(cli_func_t) |
| 268 |
120 |
cli_debug_srandom(struct cli *cli, const char * const *av, void *priv) |
| 269 |
|
{ |
| 270 |
120 |
unsigned seed = 1; |
| 271 |
|
|
| 272 |
120 |
(void)priv; |
| 273 |
120 |
(void)cli; |
| 274 |
120 |
if (av[2] != NULL) |
| 275 |
0 |
seed = strtoul(av[2], NULL, 0); |
| 276 |
120 |
VRND_SeedTestable(seed); |
| 277 |
120 |
} |
| 278 |
|
|
| 279 |
|
static struct cli_proto debug_cmds[] = { |
| 280 |
|
{ CLICMD_DEBUG_XID, "d", cli_debug_xid }, |
| 281 |
|
{ CLICMD_DEBUG_SHUTDOWN_DELAY, "d", cli_debug_shutdown_delay }, |
| 282 |
|
{ CLICMD_DEBUG_SRANDOM, "d", cli_debug_srandom }, |
| 283 |
|
{ NULL } |
| 284 |
|
}; |
| 285 |
|
|
| 286 |
|
/*-------------------------------------------------------------------- |
| 287 |
|
* XXX: Think more about which order we start things |
| 288 |
|
*/ |
| 289 |
|
|
| 290 |
|
#if defined(__FreeBSD__) && __FreeBSD_version >= 1000000 |
| 291 |
|
static void |
| 292 |
0 |
child_malloc_fail(void *p, const char *s) |
| 293 |
|
{ |
| 294 |
0 |
VSL(SLT_Error, NO_VXID, "MALLOC ERROR: %s (%p)", s, p); |
| 295 |
0 |
fprintf(stderr, "MALLOC ERROR: %s (%p)\n", s, p); |
| 296 |
0 |
WRONG("Malloc Error"); |
| 297 |
0 |
} |
| 298 |
|
#endif |
| 299 |
|
|
| 300 |
|
/*===================================================================== |
| 301 |
|
* signal handler for child process |
| 302 |
|
*/ |
| 303 |
|
|
| 304 |
|
static void v_noreturn_ v_matchproto_() |
| 305 |
80 |
child_signal_handler(int s, siginfo_t *si, void *c) |
| 306 |
|
{ |
| 307 |
|
char buf[1024]; |
| 308 |
|
struct sigaction sa; |
| 309 |
|
struct req *req; |
| 310 |
80 |
const char *a, *p, *info = NULL; |
| 311 |
|
|
| 312 |
80 |
(void)c; |
| 313 |
|
/* Don't come back */ |
| 314 |
80 |
memset(&sa, 0, sizeof sa); |
| 315 |
80 |
sa.sa_handler = SIG_DFL; |
| 316 |
80 |
(void)sigaction(SIGSEGV, &sa, NULL); |
| 317 |
80 |
(void)sigaction(SIGBUS, &sa, NULL); |
| 318 |
80 |
(void)sigaction(SIGABRT, &sa, NULL); |
| 319 |
|
|
| 320 |
80 |
while (s == SIGSEGV || s == SIGBUS) { |
| 321 |
80 |
req = THR_GetRequest(); |
| 322 |
80 |
if (req == NULL || req->wrk == NULL) |
| 323 |
0 |
break; |
| 324 |
80 |
a = TRUST_ME(si->si_addr); |
| 325 |
80 |
p = TRUST_ME(req->wrk); |
| 326 |
80 |
p += sizeof *req->wrk; |
| 327 |
|
// rough safe estimate - top of stack |
| 328 |
80 |
if (a > p + cache_param->wthread_stacksize) |
| 329 |
0 |
break; |
| 330 |
80 |
if (a < p - 2 * cache_param->wthread_stacksize) |
| 331 |
40 |
break; |
| 332 |
40 |
info = "\nTHIS PROBABLY IS A STACK OVERFLOW - " |
| 333 |
|
"check thread_pool_stack parameter"; |
| 334 |
40 |
break; |
| 335 |
|
} |
| 336 |
80 |
bprintf(buf, "Signal %d (%s) received at %p si_code %d%s", |
| 337 |
|
s, strsignal(s), si->si_addr, si->si_code, |
| 338 |
|
info ? info : ""); |
| 339 |
|
|
| 340 |
80 |
VAS_Fail(__func__, |
| 341 |
|
__FILE__, |
| 342 |
|
__LINE__, |
| 343 |
80 |
buf, |
| 344 |
|
VAS_WRONG); |
| 345 |
|
} |
| 346 |
|
|
| 347 |
|
/*===================================================================== |
| 348 |
|
* Magic for panicking properly on signals |
| 349 |
|
*/ |
| 350 |
|
|
| 351 |
|
static void |
| 352 |
37994 |
child_sigmagic(size_t altstksz) |
| 353 |
|
{ |
| 354 |
|
struct sigaction sa; |
| 355 |
|
|
| 356 |
37994 |
memset(&sa, 0, sizeof sa); |
| 357 |
|
|
| 358 |
37994 |
size_t sz = vmax_t(size_t, SIGSTKSZ + 4096, altstksz); |
| 359 |
37994 |
altstack.ss_sp = mmap(NULL, sz, PROT_READ | PROT_WRITE, |
| 360 |
|
MAP_PRIVATE | MAP_ANONYMOUS, |
| 361 |
|
-1, 0); |
| 362 |
37994 |
AN(altstack.ss_sp != MAP_FAILED); |
| 363 |
37994 |
AN(altstack.ss_sp); |
| 364 |
37994 |
altstack.ss_size = sz; |
| 365 |
37994 |
altstack.ss_flags = 0; |
| 366 |
37994 |
sa.sa_flags |= SA_ONSTACK; |
| 367 |
|
|
| 368 |
37994 |
THR_Init(); |
| 369 |
|
|
| 370 |
37994 |
sa.sa_sigaction = child_signal_handler; |
| 371 |
37994 |
sa.sa_flags |= SA_SIGINFO; |
| 372 |
37994 |
(void)sigaction(SIGBUS, &sa, NULL); |
| 373 |
37994 |
(void)sigaction(SIGABRT, &sa, NULL); |
| 374 |
37994 |
(void)sigaction(SIGSEGV, &sa, NULL); |
| 375 |
37994 |
} |
| 376 |
|
|
| 377 |
|
static void |
| 378 |
86 |
cli_quit(int sig) |
| 379 |
|
{ |
| 380 |
|
|
| 381 |
86 |
if (!IS_CLI()) { |
| 382 |
0 |
PTOK(pthread_kill(cli_thread, sig)); |
| 383 |
0 |
return; |
| 384 |
|
} |
| 385 |
|
|
| 386 |
86 |
WRONG("It's time for the big quit"); |
| 387 |
0 |
} |
| 388 |
|
|
| 389 |
|
/*===================================================================== |
| 390 |
|
* XXX Generalize? |
| 391 |
|
*/ |
| 392 |
|
|
| 393 |
|
static void |
| 394 |
37520 |
bit_set(volatile uint8_t *p, unsigned no) |
| 395 |
|
{ |
| 396 |
|
uint8_t b; |
| 397 |
|
|
| 398 |
37520 |
p += (no >> 3); |
| 399 |
37520 |
b = (0x80 >> (no & 7)); |
| 400 |
37520 |
*p |= b; |
| 401 |
37520 |
} |
| 402 |
|
|
| 403 |
|
/*===================================================================== |
| 404 |
|
* Run the child process |
| 405 |
|
*/ |
| 406 |
|
|
| 407 |
|
static void v_matchproto_(cli_func_t) |
| 408 |
37840 |
ccf_child_start(struct cli *cli, const char * const *av, void *priv) |
| 409 |
|
{ |
| 410 |
37840 |
(void)av; |
| 411 |
37840 |
(void)priv; |
| 412 |
|
|
| 413 |
37840 |
VCA_Start(cli); |
| 414 |
37840 |
} |
| 415 |
|
|
| 416 |
|
static struct cli_proto child_cmds[] = { |
| 417 |
|
{ CLICMD_SERVER_START, "", ccf_child_start }, |
| 418 |
|
{ NULL } |
| 419 |
|
}; |
| 420 |
|
|
| 421 |
|
#define CAP 17U |
| 422 |
|
|
| 423 |
|
static void |
| 424 |
114102 |
t_vscarab1(struct vscarab *scarab) |
| 425 |
|
{ |
| 426 |
|
struct viov *v; |
| 427 |
|
uint64_t sum; |
| 428 |
|
|
| 429 |
114102 |
VSCARAB_CHECK_NOTNULL(scarab); |
| 430 |
114102 |
AZ(scarab->used); |
| 431 |
|
|
| 432 |
114102 |
v = VSCARAB_GET(scarab); |
| 433 |
114102 |
AN(v); |
| 434 |
114102 |
v->lease = 12; |
| 435 |
|
|
| 436 |
114102 |
VSCARAB_ADD(scarab, (struct viov){.lease = 30}); |
| 437 |
|
|
| 438 |
114102 |
sum = 0; |
| 439 |
342306 |
VSCARAB_FOREACH(v, scarab) |
| 440 |
228204 |
sum += v->lease; |
| 441 |
|
|
| 442 |
114102 |
assert(sum == 42); |
| 443 |
114102 |
} |
| 444 |
|
|
| 445 |
|
static void |
| 446 |
38034 |
t_vscarab(void) |
| 447 |
|
{ |
| 448 |
|
char testbuf[VSCARAB_SIZE(CAP)]; |
| 449 |
38034 |
struct vscarab *frombuf = (void *)testbuf; |
| 450 |
38034 |
VSCARAB_INIT(frombuf, CAP); |
| 451 |
38034 |
t_vscarab1(frombuf); |
| 452 |
|
|
| 453 |
|
// --- |
| 454 |
|
|
| 455 |
38034 |
VSCARAB_LOCAL(scarab, CAP); |
| 456 |
38034 |
t_vscarab1(scarab); |
| 457 |
|
|
| 458 |
|
// --- |
| 459 |
|
|
| 460 |
|
struct vscarab *heap; |
| 461 |
38034 |
VSCARAB_ALLOC(heap, CAP); |
| 462 |
38034 |
t_vscarab1(heap); |
| 463 |
38034 |
free(heap); |
| 464 |
38034 |
} |
| 465 |
|
|
| 466 |
|
void |
| 467 |
38034 |
child_main(int sigmagic, size_t altstksz) |
| 468 |
|
{ |
| 469 |
38034 |
t_vscarab(); |
| 470 |
|
|
| 471 |
38034 |
if (sigmagic) |
| 472 |
37994 |
child_sigmagic(altstksz); |
| 473 |
38034 |
(void)signal(SIGINT, SIG_DFL); |
| 474 |
38034 |
(void)signal(SIGTERM, SIG_DFL); |
| 475 |
38034 |
(void)signal(SIGQUIT, cli_quit); |
| 476 |
|
|
| 477 |
|
#if defined(__FreeBSD__) && __FreeBSD_version >= 1000000 |
| 478 |
38034 |
malloc_message = child_malloc_fail; |
| 479 |
|
#endif |
| 480 |
|
|
| 481 |
|
/* Before anything uses pthreads in anger */ |
| 482 |
38034 |
PTOK(pthread_mutexattr_init(&mtxattr_errorcheck)); |
| 483 |
38034 |
PTOK(pthread_mutexattr_settype(&mtxattr_errorcheck, PTHREAD_MUTEX_ERRORCHECK)); |
| 484 |
|
|
| 485 |
38034 |
cache_param = heritage.param; |
| 486 |
|
|
| 487 |
38034 |
PTOK(pthread_key_create(&req_key, NULL)); |
| 488 |
38034 |
PTOK(pthread_key_create(&bo_key, NULL)); |
| 489 |
38034 |
PTOK(pthread_key_create(&wrk_key, NULL)); |
| 490 |
38034 |
PTOK(pthread_key_create(&witness_key, free)); |
| 491 |
38034 |
PTOK(pthread_key_create(&name_key, NULL)); |
| 492 |
38034 |
PTOK(pthread_key_create(&panic_key, NULL)); |
| 493 |
|
|
| 494 |
38034 |
THR_SetName("cache-main"); |
| 495 |
|
|
| 496 |
38034 |
PTOK(pthread_mutex_init(&cache_vrnd_mtx, &mtxattr_errorcheck)); |
| 497 |
38034 |
VRND_Lock = cache_vrnd_lock; |
| 498 |
38034 |
VRND_Unlock = cache_vrnd_unlock; |
| 499 |
|
|
| 500 |
38034 |
VSM_Init(); /* First, LCK needs it. */ |
| 501 |
|
|
| 502 |
38034 |
LCK_Init(); /* Second, locking */ |
| 503 |
|
|
| 504 |
38034 |
Lck_New(&vxid_lock, lck_vxid); |
| 505 |
|
|
| 506 |
38034 |
CLI_Init(); |
| 507 |
38034 |
PAN_Init(); |
| 508 |
38034 |
VFP_Init(); |
| 509 |
|
|
| 510 |
38034 |
ObjInit(); |
| 511 |
|
|
| 512 |
38034 |
WRK_Init(); |
| 513 |
|
|
| 514 |
38034 |
VCL_Init(); |
| 515 |
38034 |
VCL_VRT_Init(); |
| 516 |
|
|
| 517 |
38034 |
HTTP_Init(); |
| 518 |
|
|
| 519 |
38034 |
VBO_Init(); |
| 520 |
38034 |
VCP_Init(); |
| 521 |
38034 |
VBP_Init(); |
| 522 |
38034 |
VDI_Init(); |
| 523 |
38034 |
VBE_InitCfg(); |
| 524 |
38034 |
Pool_Init(); |
| 525 |
38034 |
V1P_Init(); |
| 526 |
38034 |
V2D_Init(); |
| 527 |
|
|
| 528 |
38034 |
EXP_Init(); |
| 529 |
38034 |
HSH_Init(heritage.hash); |
| 530 |
38034 |
BAN_Init(); |
| 531 |
|
|
| 532 |
38034 |
VCA_Init(); |
| 533 |
|
|
| 534 |
38034 |
STV_open(); |
| 535 |
|
|
| 536 |
38034 |
VMOD_Init(); |
| 537 |
|
|
| 538 |
38034 |
BAN_Compile(); |
| 539 |
|
|
| 540 |
38034 |
VRND_SeedAll(); |
| 541 |
|
|
| 542 |
|
|
| 543 |
38034 |
CLI_AddFuncs(debug_cmds); |
| 544 |
38034 |
CLI_AddFuncs(child_cmds); |
| 545 |
|
|
| 546 |
|
#ifdef WITH_PERSISTENT_STORAGE |
| 547 |
|
/* Wait for persistent storage to load if asked to */ |
| 548 |
38034 |
if (FEATURE(FEATURE_WAIT_SILO)) |
| 549 |
960 |
SMP_Ready(); |
| 550 |
|
#endif |
| 551 |
|
|
| 552 |
38034 |
CLI_Run(); |
| 553 |
|
|
| 554 |
38034 |
bit_set(cache_param->debug_bits, DBG_VCLREL); |
| 555 |
|
|
| 556 |
38034 |
if (shutdown_delay > 0) |
| 557 |
0 |
VTIM_sleep(shutdown_delay); |
| 558 |
|
|
| 559 |
38034 |
VCA_Shutdown(); |
| 560 |
38034 |
BAN_Shutdown(); |
| 561 |
38034 |
EXP_Shutdown(); |
| 562 |
38034 |
STV_warn(); |
| 563 |
38034 |
VCL_Shutdown(); |
| 564 |
38034 |
STV_close(); |
| 565 |
|
|
| 566 |
38034 |
printf("Child dies\n"); |
| 567 |
38034 |
} |