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