]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
Now works with multiple caches
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
eb824054 3 * $Id: main.cc,v 1.303 1999/07/13 14:51:15 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 1 Startup and Main Loop
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
30a4f2a8 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
30a4f2a8 34 */
44a47c6e 35
36#include "squid.h"
37
30a4f2a8 38/* for error reporting from xmalloc and friends */
ea3a2a69 39extern void (*failure_notify) (const char *);
30a4f2a8 40
f1dc9b30 41static int opt_send_signal = -1;
f95b8144 42static int opt_no_daemon = 0;
e13ee7ad 43static int opt_parse_cfg_only = 0;
30a4f2a8 44static int httpPortNumOverride = 1;
45static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e13ee7ad 46static int configured_once = 0;
30a4f2a8 47#if MALLOC_DBG
4d64d74a 48static int malloc_debug_level = 0;
30a4f2a8 49#endif
5cd39a10 50static volatile int do_reconfigure = 0;
51static volatile int do_rotate = 0;
2681d383 52static volatile int do_shutdown = 0;
4d7add01 53
5cd39a10 54static void mainRotate(void);
55static void mainReconfigure(void);
b984c445 56static SIGHDLR rotate_logs;
57static SIGHDLR reconfigure;
58#if ALARM_UPDATES_TIME
59static SIGHDLR time_tick;
60#endif
f5b8bbc4 61static void mainInitialize(void);
f5b8bbc4 62static void usage(void);
63static void mainParseOptions(int, char **);
64static void sendSignal(void);
65static void serverConnectionsOpen(void);
bbe199dc 66static void watch_child(char **);
85407535 67static void setEffectiveUser(void);
36a97e19 68#if MEM_GEN_TRACE
69extern void log_trace_done();
70extern void log_trace_init(char *);
71#endif
d723bf6b 72static EVH SquidShutdown;
b6a2f15e 73static void mainSetCwd(void);
85407535 74
b8d8561b 75static void
0673c0ba 76usage(void)
ccff9601 77{
0ee4272b 78 fprintf(stderr,
969c39b9 79 "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
15df8349 80 " -a port Specify HTTP port number (default: %d).\n"
b6157f5e 81 " -d level Write debugging to stderr also.\n"
0ee4272b 82 " -f file Use given config-file instead of\n"
83 " %s\n"
84 " -h Print help message.\n"
e13ee7ad 85 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
86 " Parse configuration file, then send signal to \n"
87 " running copy (except -k parse) and exit.\n"
0ee4272b 88 " -s Enable logging to syslog.\n"
89 " -u port Specify ICP port number (default: %d), disable with 0.\n"
90 " -v Print version.\n"
85407535 91 " -z Create swap directories\n"
0ee4272b 92 " -C Do not catch fatal signals.\n"
93 " -D Disable initial DNS tests.\n"
a411c763 94 " -F Don't serve any requests until store is rebuilt.\n"
969c39b9 95 " -N No daemon mode.\n"
0ee4272b 96 " -R Do not set REUSEADDR on port.\n"
0ee4272b 97 " -V Virtual host httpd-accelerator.\n"
3013ac6d 98 " -X Force full debugging.\n"
429fdbec 99 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
30a4f2a8 100 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 101 exit(1);
ccff9601 102}
103
b8d8561b 104static void
105mainParseOptions(int argc, char *argv[])
090089c4 106{
090089c4 107 extern char *optarg;
4d64d74a 108 int c;
090089c4 109
723e8aa3 110 while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
090089c4 111 switch (c) {
090089c4 112 case 'C':
1758c627 113 opt_catch_signals = 0;
090089c4 114 break;
115 case 'D':
30a4f2a8 116 opt_dns_tests = 0;
090089c4 117 break;
30a4f2a8 118 case 'F':
119 opt_foreground_rebuild = 1;
090089c4 120 break;
f95b8144 121 case 'N':
122 opt_no_daemon = 1;
9e2225aa 123 break;
090089c4 124 case 'R':
3b4be6a6 125 opt_reuseaddr = 0;
090089c4 126 break;
b109de6b 127 case 'S':
128 opt_store_doublecheck = 1;
129 break;
30a4f2a8 130 case 'V':
131 vhost_mode = 1;
132 break;
e924600d 133 case 'X':
134 /* force full debugging */
135 sigusr2_handle(SIGUSR2);
136 break;
30a4f2a8 137 case 'Y':
138 opt_reload_hit_only = 1;
139 break;
140 case 'a':
141 httpPortNumOverride = atoi(optarg);
142 break;
0d90407c 143 case 'd':
723e8aa3 144 opt_debug_stderr = atoi(optarg);
0d90407c 145 break;
090089c4 146 case 'f':
00fac1f8 147 xfree(ConfigFile);
148 ConfigFile = xstrdup(optarg);
090089c4 149 break;
30a4f2a8 150 case 'h':
151 usage();
090089c4 152 break;
7690e8eb 153 case 'k':
24382924 154 if ((int) strlen(optarg) < 1)
7690e8eb 155 usage();
156 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
157 opt_send_signal = SIGHUP;
158 else if (!strncmp(optarg, "rotate", strlen(optarg)))
7e7a0442 159#ifdef _SQUID_LINUX_THREADS_
e3175d1f 160 opt_send_signal = SIGQUIT;
161#else
7690e8eb 162 opt_send_signal = SIGUSR1;
e3175d1f 163#endif
7690e8eb 164 else if (!strncmp(optarg, "debug", strlen(optarg)))
7e7a0442 165#ifdef _SQUID_LINUX_THREADS_
e3175d1f 166 opt_send_signal = SIGTRAP;
167#else
7690e8eb 168 opt_send_signal = SIGUSR2;
e3175d1f 169#endif
7690e8eb 170 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
171 opt_send_signal = SIGTERM;
6759a5fb 172 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
173 opt_send_signal = SIGINT;
7690e8eb 174 else if (!strncmp(optarg, "kill", strlen(optarg)))
175 opt_send_signal = SIGKILL;
176 else if (!strncmp(optarg, "check", strlen(optarg)))
fedac7e5 177 opt_send_signal = 0; /* SIGNULL */
e13ee7ad 178 else if (!strncmp(optarg, "parse", strlen(optarg)))
8a6218c6 179 opt_parse_cfg_only = 1; /* parse cfg file only */
7690e8eb 180 else
181 usage();
182 break;
090089c4 183 case 'm':
33ab18e8 184 if (optarg) {
30a4f2a8 185#if MALLOC_DBG
33ab18e8 186 malloc_debug_level = atoi(optarg);
187 /* NOTREACHED */
188 break;
30a4f2a8 189#else
33ab18e8 190 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
191 /* NOTREACHED */
192#endif
193 } else {
194#if XMALLOC_TRACE
195 xmalloc_trace = !xmalloc_trace;
196#else
197 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
30a4f2a8 198#endif
33ab18e8 199 }
30a4f2a8 200 case 's':
6e40f263 201 opt_syslog_enable = 1;
30a4f2a8 202 break;
203 case 'u':
204 icpPortNumOverride = atoi(optarg);
205 if (icpPortNumOverride < 0)
206 icpPortNumOverride = 0;
207 break;
208 case 'v':
209 printf("Squid Cache: Version %s\n", version_string);
210 exit(0);
211 /* NOTREACHED */
090089c4 212 case 'z':
85407535 213 opt_create_swap_dirs = 1;
090089c4 214 break;
215 case '?':
090089c4 216 default:
ccff9601 217 usage();
090089c4 218 break;
219 }
090089c4 220 }
4d64d74a 221}
090089c4 222
7a2f978b 223/* ARGSUSED */
b8d8561b 224static void
225rotate_logs(int sig)
30a4f2a8 226{
5cd39a10 227 do_rotate = 1;
30a4f2a8 228#if !HAVE_SIGACTION
229 signal(sig, rotate_logs);
230#endif
231}
232
b984c445 233#if ALARM_UPDATES_TIME
97c03d3c 234static void
235time_tick(int sig)
236{
237 getCurrentTime();
238 alarm(1);
239#if !HAVE_SIGACTION
240 signal(sig, time_tick);
241#endif
242}
38d04788 243
b984c445 244#endif
97c03d3c 245
7a2f978b 246/* ARGSUSED */
b8d8561b 247static void
248reconfigure(int sig)
30a4f2a8 249{
5cd39a10 250 do_reconfigure = 1;
30a4f2a8 251#if !HAVE_SIGACTION
252 signal(sig, reconfigure);
253#endif
254}
255
b8d8561b 256void
257shut_down(int sig)
30a4f2a8 258{
2681d383 259 do_shutdown = sig == SIGINT ? -1 : 1;
cadc2d55 260#ifdef KILL_PARENT_OPT
5cd39a10 261 if (getppid() > 1) {
262 debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
263 kill(getppid(), sig);
88738790 264 }
cadc2d55 265#endif
6e40f263 266#if SA_RESETHAND == 0
267 signal(SIGTERM, SIG_DFL);
268 signal(SIGINT, SIG_DFL);
269#endif
30a4f2a8 270}
271
24382924 272static void
0673c0ba 273serverConnectionsOpen(void)
4d64d74a 274{
15df8349 275 clientHttpConnectionsOpen();
276 icpConnectionsOpen();
ace287ee 277#if USE_HTCP
278 htcpInit();
279#endif
678c6099 280#ifdef SQUID_SNMP
3265e68d 281 snmpConnectionOpen();
320e9f36 282#endif
eb824054 283#if USE_WCCP
320e9f36 284 wccpConnectionOpen();
2bbd722b 285#endif
5ecceaa4 286 clientdbInit();
16b204c4 287 icmpOpen();
67508012 288 netdbInit();
f899fac1 289 asnInit();
85034133 290 peerSelectInit();
afd88fbe 291#if USE_CARP
292 carpInit();
293#endif
5f3f8d0e 294}
295
b8d8561b 296void
0673c0ba 297serverConnectionsClose(void)
5f3f8d0e 298{
0a5a8601 299 assert(shutting_down || reconfiguring);
c0fbae16 300 clientHttpConnectionsClose();
17e6c0a1 301 icpConnectionShutdown();
72549e05 302#if USE_HTCP
303 htcpSocketShutdown();
304#endif
c0fbae16 305 icmpClose();
15df8349 306#ifdef SQUID_SNMP
17e6c0a1 307 snmpConnectionShutdown();
320e9f36 308#endif
eb824054 309#if USE_WCCP
320e9f36 310 wccpConnectionShutdown();
15df8349 311#endif
4bac8de8 312 asnFreeMemory();
5f3f8d0e 313}
314
b8d8561b 315static void
dbe4fd8e 316mainReconfigure(void)
5f3f8d0e 317{
a60f7062 318 debug(1, 1) ("Restarting Squid Cache (version %s)...\n", version_string);
5cd39a10 319 reconfiguring = 1;
0ffd22bc 320 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
15df8349 321 serverConnectionsClose();
17e6c0a1 322 icpConnectionClose();
72549e05 323#if USE_HTCP
324 htcpSocketClose();
325#endif
17e6c0a1 326#ifdef SQUID_SNMP
327 snmpConnectionClose();
320e9f36 328#endif
eb824054 329#if USE_WCCP
320e9f36 330 wccpConnectionClose();
17e6c0a1 331#endif
74addf6c 332 dnsShutdown();
eb824054 333#if !USE_DNSSERVERS
7b724b86 334 idnsShutdown();
eb824054 335#endif
74addf6c 336 redirectShutdown();
337 authenticateShutdown();
2db68ce5 338 storeDirCloseSwapLogs();
c68e9c6b 339 errorClean();
9c021a38 340 mimeFreeMemory();
00fac1f8 341 parseConfigFile(ConfigFile);
b6f794d6 342 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 343 ipcache_restart(); /* clear stuck entries */
344 fqdncache_restart(); /* sigh, fqdncache too */
53ad48e6 345 errorInitialize(); /* reload error pages */
74addf6c 346 dnsInit();
eb824054 347#if !USE_DNSSERVERS
7b724b86 348 idnsInit();
eb824054 349#endif
74addf6c 350 redirectInit();
351 authenticateInit();
0ffd22bc 352 serverConnectionsOpen();
e06ce23a 353 if (theOutIcpConnection >= 0) {
5942e8d4 354 if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
e06ce23a 355 neighbors_open(theOutIcpConnection);
356 else
357 debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
358 }
2db68ce5 359 storeDirOpenSwapLogs();
9c021a38 360 mimeInit(Config.mimeTablePathname);
b8890359 361 writePidFile(); /* write PID file */
aebbcd07 362 debug(1, 1) ("Ready to serve requests.\n");
5cd39a10 363 reconfiguring = 0;
364}
365
366static void
367mainRotate(void)
368{
369 icmpClose();
370 _db_rotate_log(); /* cache.log */
371 storeDirWriteCleanLogs(1);
372 storeLogRotate(); /* store.log */
373 accessLogRotate(); /* access.log */
374 useragentRotateLog(); /* useragent.log */
375 icmpOpen();
5f3f8d0e 376}
377
067bea91 378static void
85407535 379setEffectiveUser(void)
380{
381 leave_suid(); /* Run as non privilegied user */
cd377065 382#ifdef _SQUID_OS2_
383 return;
384#endif
85407535 385 if (geteuid() == 0) {
386 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
387 debug(0, 0) ("start Squid as root, then you must configure\n");
388 debug(0, 0) ("it to run as a non-priveledged user with the\n");
389 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
390 fatal("Don't run Squid as root, set 'cache_effective_user'!");
391 }
392}
393
b6a2f15e 394static void
395mainSetCwd(void)
396{
397 if (Config.coredump_dir) {
398 if (!chdir(Config.coredump_dir)) {
399 debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
400 return;
401 } else {
402 debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
403 }
404 }
405 if (!Config.effectiveUser) {
406 char *p = getcwd(NULL, 0);
407 debug(0, 1) ("Current Directory is %s\n", p);
408 xfree(p);
409 return;
410 }
411 /* we were probably started as root, so cd to a swap
412 * directory in case we dump core */
413 if (!chdir(storeSwapDir(0))) {
414 debug(0, 1) ("Set Current Directory to %s\n", storeSwapDir(0));
415 return;
416 } else {
417 debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror());
418 fatal_dump("Cannot cd to swap directory?");
419 }
420}
421
b8d8561b 422static void
0673c0ba 423mainInitialize(void)
5f3f8d0e 424{
1758c627 425 if (opt_catch_signals) {
30a4f2a8 426 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
427 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 428 }
30a4f2a8 429 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
430 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 431
85407535 432 setEffectiveUser();
270b86af 433 assert(Config.Port.http);
30a4f2a8 434 if (httpPortNumOverride != 1)
270b86af 435 Config.Port.http->i = (u_short) httpPortNumOverride;
30a4f2a8 436 if (icpPortNumOverride != 1)
f2052513 437 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 438
b6f794d6 439 _db_init(Config.Log.log, Config.debugOptions);
5c5783a2 440 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
71a17702 441#if MEM_GEN_TRACE
442 log_trace_init("/tmp/squid.alloc");
443#endif
a3d5953d 444 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
30a4f2a8 445 version_string,
446 CONFIG_HOST_TYPE);
aebbcd07 447 debug(1, 1) ("Process ID %d\n", (int) getpid());
a3d5953d 448 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 449
9f75c559 450 if (!configured_once)
234967c9 451 disk_init(); /* disk_init must go before ipcache_init() */
5f3f8d0e 452 ipcache_init();
f88bb09c 453 fqdncache_init();
74addf6c 454 dnsInit();
eb824054 455#if !USE_DNSSERVERS
7b724b86 456 idnsInit();
eb824054 457#endif
74addf6c 458 redirectInit();
459 authenticateInit();
b012353a 460 useragentOpenLog();
2ac76861 461 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
2246b732 462 httpReplyInitModule(); /* must go before accepting replies */
9b312a19 463 errorInitialize();
7a2f978b 464 accessLogInit();
3898f57f 465#if USE_IDENT
05832ae1 466 identInit();
3898f57f 467#endif
5e14bf6d 468#ifdef SQUID_SNMP
469 snmpInit();
470#endif
eb824054 471#if USE_WCCP
320e9f36 472 wccpInit();
473#endif
30a4f2a8 474#if MALLOC_DBG
5f3f8d0e 475 malloc_debug(0, malloc_debug_level);
476#endif
477
dbe4fd8e 478 if (!configured_once) {
429fdbec 479 unlinkdInit();
7111c86a 480 urlInitialize();
22f3fd98 481 cachemgrInit();
f6308664 482 eventInit(); /* eventInit() before statInit() */
a7c05555 483 statInit();
5f3f8d0e 484 storeInit();
b6a2f15e 485 mainSetCwd();
5f3f8d0e 486 /* after this point we want to see the mallinfo() output */
487 do_mallinfo = 1;
812ed90c 488 mimeInit(Config.mimeTablePathname);
603a02fd 489 pconnInit();
1c3e77cd 490 refreshInit();
0d7e5d78 491#if DELAY_POOLS
95e36d02 492 delayPoolsInit();
0d7e5d78 493#endif
8ddcc35d 494 fwdInit();
5f3f8d0e 495 }
2285407f 496 serverConnectionsOpen();
e06ce23a 497 if (theOutIcpConnection >= 0) {
5942e8d4 498 if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
e06ce23a 499 neighbors_open(theOutIcpConnection);
500 else
501 debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
502 }
dbe4fd8e 503 if (!configured_once)
0a5b9b32 504 writePidFile(); /* write PID file */
505
7e7a0442 506#ifdef _SQUID_LINUX_THREADS_
e3175d1f 507 squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
508 squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
509#else
30a4f2a8 510 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
511 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
9fc0b4b8 512#endif
30a4f2a8 513 squid_signal(SIGHUP, reconfigure, SA_RESTART);
514 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
515 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
b984c445 516#if ALARM_UPDATES_TIME
97c03d3c 517 squid_signal(SIGALRM, time_tick, SA_RESTART);
518 alarm(1);
b984c445 519#endif
58a39dc9 520 memCheckInit();
aebbcd07 521 debug(1, 1) ("Ready to serve requests.\n");
dbe4fd8e 522 if (!configured_once) {
52040193 523 eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
17a0a4ee 524 if (Config.onoff.announce)
52040193 525 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
526 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
527 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
eb824054 528#if USE_WCCP
f6308664 529 if (Config.Wccp.router.s_addr != inet_addr("0.0.0.0"))
320e9f36 530 eventAdd("wccpHereIam", wccpHereIam, NULL, 10.0, 1);
531#endif
4d7add01 532 }
dbe4fd8e 533 configured_once = 1;
4d64d74a 534}
535
b8d8561b 536int
537main(int argc, char **argv)
4d64d74a 538{
539 int errcount = 0;
4d64d74a 540 int n; /* # of GC'd objects */
bc528c78 541 time_t loop_delay;
4d64d74a 542
88738790 543 debug_log = stderr;
e83892e9 544 if (FD_SETSIZE < Squid_MaxFD)
545 Squid_MaxFD = FD_SETSIZE;
399e85ea 546
7328e889 547 /* call mallopt() before anything else */
0b29fe44 548#if HAVE_MALLOPT
7328e889 549#ifdef M_GRAIN
550 /* Round up all sizes to a multiple of this */
551 mallopt(M_GRAIN, 16);
552#endif
553#ifdef M_MXFAST
554 /* biggest size that is considered a small block */
555 mallopt(M_MXFAST, 256);
556#endif
557#ifdef M_NBLKS
558 /* allocate this many small blocks at once */
559 mallopt(M_NLBLKS, 32);
560#endif
561#endif /* HAVE_MALLOPT */
562
30a4f2a8 563 memset(&local_addr, '\0', sizeof(struct in_addr));
429fdbec 564 safe_inet_addr(localhost, &local_addr);
28070024 565 memset(&any_addr, '\0', sizeof(struct in_addr));
429fdbec 566 safe_inet_addr("0.0.0.0", &any_addr);
28070024 567 memset(&no_addr, '\0', sizeof(struct in_addr));
429fdbec 568 safe_inet_addr("255.255.255.255", &no_addr);
88738790 569 squid_srandom(time(NULL));
4d64d74a 570
f2908497 571 getCurrentTime();
572 squid_start = current_time;
4d64d74a 573 failure_notify = fatal_dump;
574
575 mainParseOptions(argc, argv);
576
e13ee7ad 577 /* parse configuration file
578 * note: in "normal" case this used to be called from mainInitialize() */
579 {
580 int parse_err;
581 if (!ConfigFile)
582 ConfigFile = xstrdup(DefaultConfigFile);
3cc5715b 583 assert(!configured_once);
584 cbdataInit();
5d620373 585#if USE_LEAKFINDER
586 leakInit();
587#endif
3cc5715b 588 memInit(); /* memInit is required for config parsing */
e13ee7ad 589 parse_err = parseConfigFile(ConfigFile);
8a6218c6 590
e13ee7ad 591 if (opt_parse_cfg_only)
592 return parse_err;
593 }
594
7690e8eb 595 /* send signal to running copy and exit */
596 if (opt_send_signal != -1) {
597 sendSignal();
598 /* NOTREACHED */
599 }
85407535 600 if (opt_create_swap_dirs) {
067bea91 601 setEffectiveUser();
602 debug(0, 0) ("Creating Swap Directories\n");
603 storeCreateSwapDirectories();
604 return 0;
605 }
f95b8144 606 if (!opt_no_daemon)
bbe199dc 607 watch_child(argv);
4d64d74a 608 setMaxFD();
609
1758c627 610 if (opt_catch_signals)
e83892e9 611 for (n = Squid_MaxFD; n > 2; n--)
30a4f2a8 612 close(n);
4d64d74a 613
e13ee7ad 614 /* init comm module */
4d64d74a 615 comm_init();
6a988308 616 comm_select_init();
4d64d74a 617
54f742e7 618 if (opt_no_daemon) {
619 /* we have to init fdstat here. */
620 fd_open(0, FD_LOG, "stdin");
621 fd_open(1, FD_LOG, "stdout");
622 fd_open(2, FD_LOG, "stderr");
623 }
4d64d74a 624 mainInitialize();
625
090089c4 626 /* main loop */
983061ed 627 for (;;) {
5cd39a10 628 if (do_reconfigure) {
969c39b9 629 mainReconfigure();
5cd39a10 630 do_reconfigure = 0;
631 } else if (do_rotate) {
632 mainRotate();
633 do_rotate = 0;
2681d383 634 } else if (do_shutdown) {
73c9ccc5 635 time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
5cd39a10 636 debug(1, 1) ("Preparing for shutdown after %d requests\n",
637 Counter.client_http.requests);
638 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
73c9ccc5 639 wait);
2681d383 640 do_shutdown = 0;
641 shutting_down = 1;
d723bf6b 642 serverConnectionsClose();
74addf6c 643 dnsShutdown();
eb824054 644#if !USE_DNSSERVERS
7b724b86 645 idnsShutdown();
eb824054 646#endif
74addf6c 647 redirectShutdown();
648 authenticateShutdown();
d723bf6b 649 eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
30a4f2a8 650 }
48f44632 651 eventRun();
652 if ((loop_delay = eventNextTime()) < 0)
4d7add01 653 loop_delay = 0;
812ed90c 654#if HAVE_POLL
655 switch (comm_poll(loop_delay)) {
656#else
9ca89c5a 657 switch (comm_select(loop_delay)) {
812ed90c 658#endif
090089c4 659 case COMM_OK:
234967c9 660 errcount = 0; /* reset if successful */
090089c4 661 break;
662 case COMM_ERROR:
663 errcount++;
a3d5953d 664 debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
090089c4 665 if (errcount == 10)
4d64d74a 666 fatal_dump("Select Loop failed!");
090089c4 667 break;
9ca89c5a 668 case COMM_TIMEOUT:
6c93e119 669 break;
d723bf6b 670 case COMM_SHUTDOWN:
671 SquidShutdown(NULL);
672 break;
090089c4 673 default:
6eb42cae 674 fatal_dump("MAIN: Internal error -- this should never happen.");
090089c4 675 break;
676 }
677 }
678 /* NOTREACHED */
983061ed 679 return 0;
090089c4 680}
7690e8eb 681
b8d8561b 682static void
0673c0ba 683sendSignal(void)
7690e8eb 684{
ff8d0ea6 685 pid_t pid;
fedac7e5 686 debug_log = stderr;
fedac7e5 687 pid = readPidFile();
688 if (pid > 1) {
689 if (kill(pid, opt_send_signal) &&
690 /* ignore permissions if just running check */
691 !(opt_send_signal == 0 && errno == EPERM)) {
692 fprintf(stderr, "%s: ERROR: Could not send ", appname);
693 fprintf(stderr, "signal %d to process %d: %s\n",
41d30aa8 694 opt_send_signal, (int) pid, xstrerror());
7690e8eb 695 exit(1);
696 }
fedac7e5 697 } else {
698 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
699 exit(1);
7690e8eb 700 }
fedac7e5 701 /* signal successfully sent */
702 exit(0);
703}
f95b8144 704
705static void
bbe199dc 706watch_child(char *argv[])
f95b8144 707{
708 char *prog;
f95b8144 709 int failcount = 0;
710 time_t start;
711 time_t stop;
712#ifdef _SQUID_NEXT_
713 union wait status;
714#else
715 int status;
716#endif
e3a3b845 717 pid_t pid;
54f742e7 718 int i;
f95b8144 719 if (*(argv[0]) == '(')
720 return;
54f742e7 721 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
722 if ((pid = fork()) < 0)
723 syslog(LOG_ALERT, "fork failed: %s", xstrerror());
724 else if (pid > 0)
725 exit(0);
726 if (setsid() < 0)
727 syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
728#ifdef TIOCNOTTY
729 if ((i = open("/dev/tty", O_RDWR)) >= 0) {
730 ioctl(i, TIOCNOTTY, NULL);
731 close(i);
732 }
733#endif
734 for (i = 0; i < Squid_MaxFD; i++)
735 close(i);
1ecaa0a0 736#if NOT_NEEDED
54f742e7 737 umask(0);
1ecaa0a0 738#endif
f95b8144 739 for (;;) {
54f742e7 740 if ((pid = fork()) == 0) {
f95b8144 741 /* child */
742 prog = xstrdup(argv[0]);
bbe199dc 743 argv[0] = xstrdup("(squid)");
744 execvp(prog, argv);
54f742e7 745 syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
f95b8144 746 }
54f742e7 747 /* parent */
748 syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
749 time(&start);
750 squid_signal(SIGINT, SIG_IGN, SA_RESTART);
f95b8144 751#ifdef _SQUID_NEXT_
54f742e7 752 pid = wait3(&status, 0, NULL);
f95b8144 753#else
54f742e7 754 pid = waitpid(-1, &status, 0);
f95b8144 755#endif
756 time(&stop);
54f742e7 757 if (WIFEXITED(status)) {
758 syslog(LOG_NOTICE,
759 "Squid Parent: child process %d exited with status %d",
760 pid, WEXITSTATUS(status));
761 } else if (WIFSIGNALED(status)) {
762 syslog(LOG_NOTICE,
763 "Squid Parent: child process %d exited due to signal %d",
764 pid, WTERMSIG(status));
765 } else {
766 syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
767 }
f95b8144 768 if (stop - start < 10)
769 failcount++;
a8e69881 770 else
771 failcount = 0;
54f742e7 772 if (failcount == 5) {
773 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
f95b8144 774 exit(1);
54f742e7 775 }
f95b8144 776 if (WIFEXITED(status))
777 if (WEXITSTATUS(status) == 0)
778 exit(0);
0fb4fc71 779 squid_signal(SIGINT, SIG_DFL, SA_RESTART);
f95b8144 780 sleep(3);
781 }
bbe199dc 782 /* NOTREACHED */
f95b8144 783}
fff6ad65 784
9ec1a1dc 785static void
d723bf6b 786SquidShutdown(void *unused)
fff6ad65 787{
788 debug(1, 1) ("Shutting down...\n");
789 if (Config.pidFilename && strcmp(Config.pidFilename, "none")) {
790 enter_suid();
791 safeunlink(Config.pidFilename, 0);
792 leave_suid();
793 }
d723bf6b 794 icpConnectionClose();
795#if USE_HTCP
796 htcpSocketClose();
797#endif
798#ifdef SQUID_SNMP
799 snmpConnectionClose();
320e9f36 800#endif
eb824054 801#if USE_WCCP
320e9f36 802 wccpConnectionClose();
d723bf6b 803#endif
fff6ad65 804 releaseServerSockets();
d723bf6b 805 commCloseAllSockets();
fff6ad65 806 unlinkdClose();
ddb43c58 807#if USE_ASYNC_IO
808 aioSync(); /* flush pending object writes / unlinks */
809#endif
fff6ad65 810 storeDirWriteCleanLogs(0);
811 PrintRusage();
812 dumpMallocStats();
ddb43c58 813#if USE_ASYNC_IO
814 aioSync(); /* flush log writes */
815#endif
fff6ad65 816 storeLogClose();
817 accessLogClose();
ddb43c58 818#if USE_ASYNC_IO
819 aioSync(); /* flush log close */
820#endif
33ab18e8 821#if PURIFY || XMALLOC_TRACE
fff6ad65 822 configFreeMemory();
823 storeFreeMemory();
33ab18e8 824 /*stmemFreeMemory(); */
fff6ad65 825 netdbFreeMemory();
826 ipcacheFreeMemory();
827 fqdncacheFreeMemory();
828 asnFreeMemory();
26a369ba 829 clientdbFreeMemory();
7021844c 830 httpHeaderCleanModule();
d2db411c 831 statFreeMemory();
f1fc2a8d 832 eventFreeMemory();
c68e9c6b 833 mimeFreeMemory();
834 errorClean();
fff6ad65 835#endif
26a369ba 836#if !XMALLOC_TRACE
54f742e7 837 if (opt_no_daemon) {
838 file_close(0);
839 file_close(1);
840 file_close(2);
841 }
33ab18e8 842#endif
fff6ad65 843 fdDumpOpen();
844 fdFreeMemory();
ddb43c58 845 memClean();
33ab18e8 846#if XMALLOC_TRACE
26a369ba 847 xmalloc_find_leaks();
848 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
33ab18e8 849#endif
36a97e19 850#if MEM_GEN_TRACE
399e85ea 851 log_trace_done();
36a97e19 852#endif
a60f7062 853 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
fff6ad65 854 version_string);
855 fclose(debug_log);
856 exit(0);
857}