]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
Documented cachemgr.cgi purpose and configuration
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
478c4f2f 3 * $Id: main.cc,v 1.409 2005/04/23 12:28:11 serassio Exp $
30a4f2a8 4 *
5 * DEBUG: section 1 Startup and Main Loop
6 * AUTHOR: Harvest Derived
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see 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"
450e0c10 37#include "AccessLogEntry.h"
e6ccf245 38#include "authenticate.h"
39#include "Store.h"
40#include "ICP.h"
528b2c61 41#include "HttpReply.h"
42#include "Mem.h"
b0dd28ba 43#include "ACLASN.h"
44#include "ACL.h"
75faaa7a 45#include "htcp.h"
59b2d47f 46#include "StoreFileSystem.h"
b9ae18aa 47#include "DiskIO/DiskIOModule.h"
f900210a 48#include "comm.h"
c8f4eac4 49#include "SwapDir.h"
44a47c6e 50
1a774556 51#if USE_WIN32_SERVICE
52
53#include "squid_windows.h"
54#include <process.h>
55
56static int opt_install_service = FALSE;
57static int opt_remove_service = FALSE;
58static int opt_signal_service = FALSE;
59static int opt_command_line = FALSE;
60extern void WIN32_svcstatusupdate(DWORD, DWORD);
61void WINAPI WIN32_svcHandler(DWORD);
62
63#endif
64
30a4f2a8 65/* for error reporting from xmalloc and friends */
b293c4d8 66SQUIDCEXTERN void (*failure_notify) (const char *);
30a4f2a8 67
e13ee7ad 68static int opt_parse_cfg_only = 0;
5e6d4736 69static char *opt_syslog_facility = NULL;
30a4f2a8 70static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
e13ee7ad 71static int configured_once = 0;
30a4f2a8 72#if MALLOC_DBG
4d64d74a 73static int malloc_debug_level = 0;
30a4f2a8 74#endif
5cd39a10 75static volatile int do_reconfigure = 0;
76static volatile int do_rotate = 0;
2681d383 77static volatile int do_shutdown = 0;
4d7add01 78
5cd39a10 79static void mainRotate(void);
80static void mainReconfigure(void);
f5b8bbc4 81static void mainInitialize(void);
f5b8bbc4 82static void usage(void);
83static void mainParseOptions(int, char **);
84static void sendSignal(void);
85static void serverConnectionsOpen(void);
bbe199dc 86static void watch_child(char **);
85407535 87static void setEffectiveUser(void);
36a97e19 88#if MEM_GEN_TRACE
89extern void log_trace_done();
90extern void log_trace_init(char *);
91#endif
d723bf6b 92static EVH SquidShutdown;
b6a2f15e 93static void mainSetCwd(void);
efd900cb 94static int checkRunningPid(void);
85407535 95
b293c4d8 96#ifndef _SQUID_MSWIN_
e18d7fdc 97static const char *squid_start_script = "squid_start";
b293c4d8 98#endif
e18d7fdc 99
9bc73deb 100#if TEST_ACCESS
101#include "test_access.c"
102#endif
103
b8d8561b 104static void
0673c0ba 105usage(void)
ccff9601 106{
0ee4272b 107 fprintf(stderr,
0e657244 108#if USE_WIN32_SERVICE
5e6d4736 109 "Usage: %s [-cdhirvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal] [-n name] [-O CommandLine]\n"
0e657244 110#else
5e6d4736 111 "Usage: %s [-cdhvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]\n"
0e657244 112#endif
62e76326 113 " -a port Specify HTTP port number (default: %d).\n"
114 " -d level Write debugging to stderr also.\n"
115 " -f file Use given config-file instead of\n"
116 " %s\n"
117 " -h Print help message.\n"
0e657244 118#if USE_WIN32_SERVICE
119 " -i Installs as a Windows Service (see -n option).\n"
120#endif
62e76326 121 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
122 " Parse configuration file, then send signal to \n"
123 " running copy (except -k parse) and exit.\n"
0e657244 124#if USE_WIN32_SERVICE
125 " -n name Specify Windows Service name to use for service operations\n"
126 " default is: " _WIN_SQUID_DEFAULT_SERVICE_NAME ".\n"
127 " -r Removes a Windows Service (see -n option).\n"
128#endif
5e6d4736 129 " -s | -l facility\n"
130 " Enable logging to syslog.\n"
62e76326 131 " -u port Specify ICP port number (default: %d), disable with 0.\n"
132 " -v Print version.\n"
133 " -z Create swap directories\n"
134 " -C Do not catch fatal signals.\n"
135 " -D Disable initial DNS tests.\n"
136 " -F Don't serve any requests until store is rebuilt.\n"
137 " -N No daemon mode.\n"
0e657244 138#if USE_WIN32_SERVICE
139 " -O options\n"
140 " Set Windows Service Command line options in Registry.\n"
141#endif
62e76326 142 " -R Do not set REUSEADDR on port.\n"
143 " -S Double-check swap during rebuild.\n"
144 " -V Virtual host httpd-accelerator.\n"
145 " -X Force full debugging.\n"
146 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
147 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 148 exit(1);
ccff9601 149}
150
b8d8561b 151static void
152mainParseOptions(int argc, char *argv[])
090089c4 153{
090089c4 154 extern char *optarg;
4d64d74a 155 int c;
090089c4 156
0e657244 157#if USE_WIN32_SERVICE
158
5e6d4736 159 while ((c = getopt(argc, argv, "CDFNO:RSVYXa:d:f:hik:m::n:rsl:u:vz?")) != -1)
0e657244 160#else
161
5e6d4736 162 while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::sl:u:vz?")) != -1)
0e657244 163#endif
164
9b7292ce 165 {
166
167 switch (c)
168 {
62e76326 169
170 case 'C':
171 opt_catch_signals = 0;
172 break;
173
174 case 'D':
175 opt_dns_tests = 0;
176 break;
177
178 case 'F':
179 opt_foreground_rebuild = 1;
180 break;
181
182 case 'N':
183 opt_no_daemon = 1;
184 break;
0e657244 185#if USE_WIN32_SERVICE
186
187 case 'O':
188 opt_command_line = 1;
189 WIN32_Command_Line = xstrdup(optarg);
190 break;
191#endif
62e76326 192
193 case 'R':
194 opt_reuseaddr = 0;
195 break;
196
197 case 'S':
198 opt_store_doublecheck = 1;
199 break;
200
201 case 'V':
202
203 if (Config.Sockaddr.http)
204 Config.Sockaddr.http->vhost = 1;
205
3f38a55e 206#if USE_SSL
62e76326 207
208 else if (Config.Sockaddr.https)
209 Config.Sockaddr.https->http.vhost = 1;
210
211#endif
212
213 else
214 fatal("No http_port specified\n");
215
216 break;
217
218 case 'X':
219 /* force full debugging */
220 sigusr2_handle(SIGUSR2);
221
222 break;
223
224 case 'Y':
225 opt_reload_hit_only = 1;
226
227 break;
228
0e657244 229#if USE_WIN32_SERVICE
230
231 case 'i':
232 opt_install_service = TRUE;
233
234 break;
235
236#endif
237
62e76326 238 case 'a':
239 add_http_port(optarg);
240
241 break;
242
243 case 'd':
244 opt_debug_stderr = atoi(optarg);
245
246 break;
247
248 case 'f':
249 xfree(ConfigFile);
250
251 ConfigFile = xstrdup(optarg);
252
253 break;
254
255 case 'h':
256 usage();
257
258 break;
259
260 case 'k':
261 if ((int) strlen(optarg) < 1)
262 usage();
263
264 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
265 opt_send_signal = SIGHUP;
266 else if (!strncmp(optarg, "rotate", strlen(optarg)))
7e7a0442 267#ifdef _SQUID_LINUX_THREADS_
62e76326 268
269 opt_send_signal = SIGQUIT;
270
e3175d1f 271#else
62e76326 272
273 opt_send_signal = SIGUSR1;
274
e3175d1f 275#endif
62e76326 276
277 else if (!strncmp(optarg, "debug", strlen(optarg)))
7e7a0442 278#ifdef _SQUID_LINUX_THREADS_
62e76326 279
280 opt_send_signal = SIGTRAP;
281
e3175d1f 282#else
62e76326 283
284 opt_send_signal = SIGUSR2;
285
286#endif
287
288 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
289 opt_send_signal = SIGTERM;
290 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
291 opt_send_signal = SIGINT;
292 else if (!strncmp(optarg, "kill", strlen(optarg)))
293 opt_send_signal = SIGKILL;
294 else if (!strncmp(optarg, "check", strlen(optarg)))
295 opt_send_signal = 0; /* SIGNULL */
296 else if (!strncmp(optarg, "parse", strlen(optarg)))
297 opt_parse_cfg_only = 1; /* parse cfg file only */
298 else
299 usage();
300
301 break;
302
303 case 'm':
304 if (optarg) {
30a4f2a8 305#if MALLOC_DBG
62e76326 306 malloc_debug_level = atoi(optarg);
307 /* NOTREACHED */
308 break;
30a4f2a8 309#else
62e76326 310
311 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
312 /* NOTREACHED */
33ab18e8 313#endif
62e76326 314
315 } else {
33ab18e8 316#if XMALLOC_TRACE
62e76326 317 xmalloc_trace = !xmalloc_trace;
33ab18e8 318#else
62e76326 319
320 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
30a4f2a8 321#endif
62e76326 322
323 }
324
0e657244 325#if USE_WIN32_SERVICE
326
327 case 'n':
328 xfree(WIN32_Service_name);
329
330 WIN32_Service_name = xstrdup(optarg);
331
332 opt_signal_service = TRUE;
333
334 break;
335
336 case 'r':
337 opt_remove_service = TRUE;
338
339 break;
340
341#endif
342
5e6d4736 343 case 'l':
344 opt_syslog_facility = xstrdup(optarg);
345
62e76326 346 case 's':
c307aec3 347#if HAVE_SYSLOG
62e76326 348
5e6d4736 349 _db_set_syslog(opt_syslog_facility);
0e657244 350
62e76326 351 break;
0e657244 352
c307aec3 353#else
62e76326 354
355 fatal("Logging to syslog not available on this platform");
0e657244 356
62e76326 357 /* NOTREACHED */
358#endif
359
360 case 'u':
361 icpPortNumOverride = atoi(optarg);
362
363 if (icpPortNumOverride < 0)
364 icpPortNumOverride = 0;
365
366 break;
367
368 case 'v':
369 printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string, SQUID_CONFIGURE_OPTIONS);
370
1a774556 371#if USE_WIN32_SERVICE
372
373 printf("Compiled as Windows System Service.\n");
374
375#endif
376
62e76326 377 exit(0);
378
379 /* NOTREACHED */
380
381 case 'z':
382 opt_create_swap_dirs = 1;
383
384 break;
385
386 case '?':
387
388 default:
389 usage();
390
391 break;
392 }
9b7292ce 393
090089c4 394 }
4d64d74a 395}
090089c4 396
7a2f978b 397/* ARGSUSED */
b293c4d8 398void
9b7292ce 399rotate_logs(int sig)
400{
5cd39a10 401 do_rotate = 1;
a50bfe93 402#ifndef _SQUID_MSWIN_
30a4f2a8 403#if !HAVE_SIGACTION
62e76326 404
30a4f2a8 405 signal(sig, rotate_logs);
406#endif
a50bfe93 407#endif
30a4f2a8 408}
409
7a2f978b 410/* ARGSUSED */
b293c4d8 411void
9b7292ce 412reconfigure(int sig)
413{
5cd39a10 414 do_reconfigure = 1;
a50bfe93 415#ifndef _SQUID_MSWIN_
30a4f2a8 416#if !HAVE_SIGACTION
62e76326 417
30a4f2a8 418 signal(sig, reconfigure);
419#endif
a50bfe93 420#endif
30a4f2a8 421}
422
b8d8561b 423void
9b7292ce 424shut_down(int sig)
425{
2681d383 426 do_shutdown = sig == SIGINT ? -1 : 1;
a50bfe93 427#ifndef _SQUID_MSWIN_
cadc2d55 428#ifdef KILL_PARENT_OPT
62e76326 429
5cd39a10 430 if (getppid() > 1) {
36584579 431 debugs(1, 1, "Killing RunCache, pid " << getppid());
62e76326 432
433 if (kill(getppid(), sig) < 0)
36584579 434 debugs(1, 1, "kill " << getppid() << ": " << xstrerror());
88738790 435 }
62e76326 436
cadc2d55 437#endif
6e40f263 438#if SA_RESETHAND == 0
439 signal(SIGTERM, SIG_DFL);
62e76326 440
6e40f263 441 signal(SIGINT, SIG_DFL);
62e76326 442
a50bfe93 443#endif
6e40f263 444#endif
30a4f2a8 445}
446
24382924 447static void
9b7292ce 448serverConnectionsOpen(void)
449{
d193a436 450 clientOpenListenSockets();
15df8349 451 icpConnectionsOpen();
ace287ee 452#if USE_HTCP
62e76326 453
ace287ee 454 htcpInit();
455#endif
678c6099 456#ifdef SQUID_SNMP
62e76326 457
3265e68d 458 snmpConnectionOpen();
320e9f36 459#endif
eb824054 460#if USE_WCCP
62e76326 461
320e9f36 462 wccpConnectionOpen();
2bbd722b 463#endif
62e76326 464
5ecceaa4 465 clientdbInit();
16b204c4 466 icmpOpen();
67508012 467 netdbInit();
f899fac1 468 asnInit();
b0dd28ba 469 ACL::Initialize();
85034133 470 peerSelectInit();
afd88fbe 471#if USE_CARP
62e76326 472
afd88fbe 473 carpInit();
474#endif
5f3f8d0e 475}
476
b8d8561b 477void
9b7292ce 478serverConnectionsClose(void)
479{
0a5a8601 480 assert(shutting_down || reconfiguring);
c0fbae16 481 clientHttpConnectionsClose();
17e6c0a1 482 icpConnectionShutdown();
72549e05 483#if USE_HTCP
62e76326 484
72549e05 485 htcpSocketShutdown();
486#endif
62e76326 487
c0fbae16 488 icmpClose();
15df8349 489#ifdef SQUID_SNMP
62e76326 490
17e6c0a1 491 snmpConnectionShutdown();
320e9f36 492#endif
eb824054 493#if USE_WCCP
62e76326 494
320e9f36 495 wccpConnectionShutdown();
15df8349 496#endif
62e76326 497
4bac8de8 498 asnFreeMemory();
5f3f8d0e 499}
500
b8d8561b 501static void
9b7292ce 502mainReconfigure(void)
503{
eba1bf37 504 debug(1, 1) ("Reconfiguring Squid Cache (version %s)...\n", version_string);
5cd39a10 505 reconfiguring = 1;
0ffd22bc 506 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
15df8349 507 serverConnectionsClose();
17e6c0a1 508 icpConnectionClose();
72549e05 509#if USE_HTCP
62e76326 510
72549e05 511 htcpSocketClose();
512#endif
17e6c0a1 513#ifdef SQUID_SNMP
62e76326 514
17e6c0a1 515 snmpConnectionClose();
320e9f36 516#endif
eb824054 517#if USE_WCCP
62e76326 518
320e9f36 519 wccpConnectionClose();
17e6c0a1 520#endif
3c573763 521#if USE_DNSSERVERS
62e76326 522
74addf6c 523 dnsShutdown();
3c573763 524#else
62e76326 525
7b724b86 526 idnsShutdown();
eb824054 527#endif
62e76326 528
74addf6c 529 redirectShutdown();
530 authenticateShutdown();
d9572179 531 externalAclShutdown();
2db68ce5 532 storeDirCloseSwapLogs();
2e923080 533 storeLogClose();
534 accessLogClose();
535 useragentLogClose();
536 refererCloseLog();
c68e9c6b 537 errorClean();
3aa4adbc 538 enter_suid(); /* root to read config file */
00fac1f8 539 parseConfigFile(ConfigFile);
3aa4adbc 540 setEffectiveUser();
b6f794d6 541 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 542 ipcache_restart(); /* clear stuck entries */
94439e4e 543 authenticateUserCacheRestart(); /* clear stuck ACL entries */
429fdbec 544 fqdncache_restart(); /* sigh, fqdncache too */
0e70aa1e 545 parseEtcHosts();
53ad48e6 546 errorInitialize(); /* reload error pages */
2e923080 547 accessLogInit();
548 storeLogOpen();
549 useragentOpenLog();
550 refererOpenLog();
3c573763 551#if USE_DNSSERVERS
62e76326 552
74addf6c 553 dnsInit();
3c573763 554#else
62e76326 555
7b724b86 556 idnsInit();
eb824054 557#endif
62e76326 558
74addf6c 559 redirectInit();
e6ccf245 560 authenticateInit(&Config.authConfiguration);
d9572179 561 externalAclInit();
1f38f50a 562#if USE_WCCP
62e76326 563
1f38f50a 564 wccpInit();
565#endif
62e76326 566
0ffd22bc 567 serverConnectionsOpen();
9c2e9b50 568
569 if (theOutIcpConnection >= 0)
570 neighbors_init();
571
2db68ce5 572 storeDirOpenSwapLogs();
9c2e9b50 573
9c021a38 574 mimeInit(Config.mimeTablePathname);
9c2e9b50 575
b8890359 576 writePidFile(); /* write PID file */
9c2e9b50 577
aebbcd07 578 debug(1, 1) ("Ready to serve requests.\n");
9c2e9b50 579
5cd39a10 580 reconfiguring = 0;
581}
582
583static void
9b7292ce 584mainRotate(void)
585{
5cd39a10 586 icmpClose();
3c573763 587#if USE_DNSSERVERS
62e76326 588
e40aa8da 589 dnsShutdown();
3c573763 590#endif
62e76326 591
e40aa8da 592 redirectShutdown();
593 authenticateShutdown();
d9572179 594 externalAclShutdown();
5cd39a10 595 _db_rotate_log(); /* cache.log */
596 storeDirWriteCleanLogs(1);
597 storeLogRotate(); /* store.log */
598 accessLogRotate(); /* access.log */
599 useragentRotateLog(); /* useragent.log */
fd2c5549 600 refererRotateLog(); /* referer.log */
225644d7 601#if WIP_FWD_LOG
62e76326 602
225644d7 603 fwdLogRotate();
604#endif
62e76326 605
5cd39a10 606 icmpOpen();
3c573763 607#if USE_DNSSERVERS
62e76326 608
e40aa8da 609 dnsInit();
3c573763 610#endif
62e76326 611
e40aa8da 612 redirectInit();
e6ccf245 613 authenticateInit(&Config.authConfiguration);
d9572179 614 externalAclInit();
5f3f8d0e 615}
616
067bea91 617static void
9b7292ce 618setEffectiveUser(void)
619{
85407535 620 leave_suid(); /* Run as non privilegied user */
cd377065 621#ifdef _SQUID_OS2_
62e76326 622
cd377065 623 return;
624#endif
62e76326 625
85407535 626 if (geteuid() == 0) {
62e76326 627 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
628 debug(0, 0) ("start Squid as root, then you must configure\n");
629 debug(0, 0) ("it to run as a non-priveledged user with the\n");
630 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
631 fatal("Don't run Squid as root, set 'cache_effective_user'!");
85407535 632 }
633}
634
b6a2f15e 635static void
9b7292ce 636mainSetCwd(void)
637{
4a504376 638 char pathbuf[MAXPATHLEN];
62e76326 639
b6a2f15e 640 if (Config.coredump_dir) {
62e76326 641 if (0 == strcmp("none", Config.coredump_dir)) {
642 (void) 0;
643 } else if (chdir(Config.coredump_dir) == 0) {
644 debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
645 return;
646 } else {
647 debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
648 }
b6a2f15e 649 }
62e76326 650
02e8115e 651 /* If we don't have coredump_dir or couldn't cd there, report current dir */
4a504376 652 if (getcwd(pathbuf, MAXPATHLEN)) {
62e76326 653 debug(0, 1) ("Current Directory is %s\n", pathbuf);
4a504376 654 } else {
62e76326 655 debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
4a504376 656 }
b6a2f15e 657}
658
b67e2c8c 659#if DELAY_POOLS
660#include "DelayPools.h"
661#endif
662
b8d8561b 663static void
9b7292ce 664mainInitialize(void)
665{
efd900cb 666 /* chroot if configured to run inside chroot */
62e76326 667
efd900cb 668 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
62e76326 669 fatal("failed to chroot");
efd900cb 670 }
62e76326 671
1758c627 672 if (opt_catch_signals) {
62e76326 673 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
674 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 675 }
62e76326 676
30a4f2a8 677 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
678 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 679
85407535 680 setEffectiveUser();
62e76326 681
30a4f2a8 682 if (icpPortNumOverride != 1)
62e76326 683 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 684
b6f794d6 685 _db_init(Config.Log.log, Config.debugOptions);
62e76326 686
5c5783a2 687 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
62e76326 688
71a17702 689#if MEM_GEN_TRACE
62e76326 690
71a17702 691 log_trace_init("/tmp/squid.alloc");
62e76326 692
71a17702 693#endif
62e76326 694
a3d5953d 695 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
62e76326 696 version_string,
697 CONFIG_HOST_TYPE);
698
ec4daaa5 699#ifdef _SQUID_WIN32_
b293c4d8 700
701 if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
702 debug(1, 0) ("Running as %s Windows System Service on %s\n", WIN32_Service_name, WIN32_OS_string);
703 debug(1, 0) ("Service command line is: %s\n", WIN32_Service_Command_Line);
704 } else
705 debug(1, 0) ("Running on %s\n",WIN32_OS_string);
706
707#endif
708
36584579 709 debugs(1, 1, "Process ID " << getpid());
62e76326 710
a3d5953d 711 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 712
6c1962dd 713#ifdef _SQUID_MSWIN_
714
715 debug(1, 1) ("With %d CRT stdio descriptors available\n", _getmaxstdio());
716
717 if (WIN32_Socks_initialized)
718 debug(1, 1)("Windows sockets initialized\n");
719
720#endif
721
9f75c559 722 if (!configured_once)
62e76326 723 disk_init(); /* disk_init must go before ipcache_init() */
724
5f3f8d0e 725 ipcache_init();
62e76326 726
f88bb09c 727 fqdncache_init();
62e76326 728
0e70aa1e 729 parseEtcHosts();
62e76326 730
3c573763 731#if USE_DNSSERVERS
62e76326 732
74addf6c 733 dnsInit();
62e76326 734
3c573763 735#else
62e76326 736
7b724b86 737 idnsInit();
62e76326 738
eb824054 739#endif
62e76326 740
74addf6c 741 redirectInit();
62e76326 742
e6ccf245 743 authenticateInit(&Config.authConfiguration);
62e76326 744
d9572179 745 externalAclInit();
62e76326 746
b012353a 747 useragentOpenLog();
62e76326 748
fd2c5549 749 refererOpenLog();
62e76326 750
2ac76861 751 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
62e76326 752
2246b732 753 httpReplyInitModule(); /* must go before accepting replies */
62e76326 754
9b312a19 755 errorInitialize();
62e76326 756
7a2f978b 757 accessLogInit();
62e76326 758
3898f57f 759#if USE_IDENT
62e76326 760
05832ae1 761 identInit();
62e76326 762
3898f57f 763#endif
5e14bf6d 764#ifdef SQUID_SNMP
62e76326 765
5e14bf6d 766 snmpInit();
62e76326 767
5e14bf6d 768#endif
30a4f2a8 769#if MALLOC_DBG
62e76326 770
5f3f8d0e 771 malloc_debug(0, malloc_debug_level);
62e76326 772
5f3f8d0e 773#endif
774
dbe4fd8e 775 if (!configured_once) {
a3d0a19d 776#if USE_UNLINKD
62e76326 777 unlinkdInit();
778#endif
779
780 urlInitialize();
781 cachemgrInit();
782 statInit();
783 storeInit();
784 mainSetCwd();
785 /* after this point we want to see the mallinfo() output */
786 do_mallinfo = 1;
787 mimeInit(Config.mimeTablePathname);
788 pconnInit();
789 refreshInit();
0d7e5d78 790#if DELAY_POOLS
62e76326 791
792 DelayPools::Init();
0d7e5d78 793#endif
62e76326 794
795 fwdInit();
5f3f8d0e 796 }
62e76326 797
1f38f50a 798#if USE_WCCP
799 wccpInit();
62e76326 800
1f38f50a 801#endif
62e76326 802
2285407f 803 serverConnectionsOpen();
62e76326 804
9c2e9b50 805 if (theOutIcpConnection >= 0)
806 neighbors_init();
62e76326 807
efd900cb 808 if (Config.chroot_dir)
62e76326 809 no_suid();
810
dbe4fd8e 811 if (!configured_once)
62e76326 812 writePidFile(); /* write PID file */
0a5b9b32 813
7e7a0442 814#ifdef _SQUID_LINUX_THREADS_
62e76326 815
e3175d1f 816 squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
62e76326 817
e3175d1f 818 squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
62e76326 819
e3175d1f 820#else
62e76326 821
30a4f2a8 822 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
62e76326 823
30a4f2a8 824 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
62e76326 825
9fc0b4b8 826#endif
62e76326 827
30a4f2a8 828 squid_signal(SIGHUP, reconfigure, SA_RESTART);
62e76326 829
30a4f2a8 830 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 831
30a4f2a8 832 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
62e76326 833
58a39dc9 834 memCheckInit();
62e76326 835
aebbcd07 836 debug(1, 1) ("Ready to serve requests.\n");
62e76326 837
dbe4fd8e 838 if (!configured_once) {
c8f4eac4 839 eventAdd("storeMaintain", Store::Maintain, NULL, 1.0, 1);
62e76326 840
841 if (Config.onoff.announce)
842 eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
843
844 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
845
846 eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
847
88bfe092 848#if USE_XPROF_STATS
62e76326 849
850 eventAdd("cpuProfiling", xprof_event, NULL, 1.0, 1);
851
88bfe092 852#endif
62e76326 853
854 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools, NULL, 15.0, 1);
f900210a 855
856 eventAdd("commCheckHalfClosed", commCheckHalfClosed, NULL, 1.0, false);
4d7add01 857 }
62e76326 858
dbe4fd8e 859 configured_once = 1;
4d64d74a 860}
861
6c1962dd 862#if USE_WIN32_SERVICE
863/* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */
864extern "C" void WINAPI
865 SquidMain(int argc, char **argv)
866#else
b8d8561b 867int
868main(int argc, char **argv)
9b7292ce 869#endif
870{
4d64d74a 871 int errcount = 0;
9b7292ce 872 mode_t oldmask;
4d64d74a 873
a4ba1105 874#if HAVE_SBRK
62e76326 875
9b7292ce 876 sbrk_start = sbrk(0);
a4ba1105 877#endif
878
3dc275d6 879 Debug::parseOptions("ALL,1");
9b7292ce 880 debug_log = stderr;
62e76326 881
9b7292ce 882 if (FD_SETSIZE < Squid_MaxFD)
883 Squid_MaxFD = FD_SETSIZE;
399e85ea 884
ec4daaa5 885#ifdef _SQUID_WIN32_
6c1962dd 886#ifdef USE_WIN32_SERVICE
62e76326 887
9b7292ce 888 if (WIN32_Subsystem_Init(&argc, &argv))
889 return;
6c1962dd 890
891#else
892
9b7292ce 893 {
894 int WIN32_init_err;
6c1962dd 895
9b7292ce 896 if ((WIN32_init_err = WIN32_Subsystem_Init()))
897 return WIN32_init_err;
898 }
6c1962dd 899#endif
62e76326 900
0e6d05ef 901#endif
902
9b7292ce 903 /* call mallopt() before anything else */
0b29fe44 904#if HAVE_MALLOPT
7328e889 905#ifdef M_GRAIN
9b7292ce 906 /* Round up all sizes to a multiple of this */
907 mallopt(M_GRAIN, 16);
62e76326 908
7328e889 909#endif
910#ifdef M_MXFAST
9b7292ce 911 /* biggest size that is considered a small block */
912 mallopt(M_MXFAST, 256);
62e76326 913
7328e889 914#endif
915#ifdef M_NBLKS
9b7292ce 916 /* allocate this many small blocks at once */
917 mallopt(M_NLBLKS, 32);
62e76326 918
7328e889 919#endif
920#endif /* HAVE_MALLOPT */
921
9b7292ce 922 /*
923 * The plan here is to set the umask to 007 (deny others for
924 * read,write,execute), but only if the umask is not already
925 * set. Unfortunately, there is no way to get the current
926 * umask value without setting it.
927 */
928 oldmask = umask(S_IRWXO);
62e76326 929
9b7292ce 930 if (oldmask)
931 umask(oldmask);
7e3ce7b9 932
ddfcbc22 933 memset(&local_addr, '\0', sizeof(struct IN_ADDR));
62e76326 934
9b7292ce 935 safe_inet_addr(localhost, &local_addr);
62e76326 936
ddfcbc22 937 memset(&any_addr, '\0', sizeof(struct IN_ADDR));
62e76326 938
9b7292ce 939 safe_inet_addr("0.0.0.0", &any_addr);
62e76326 940
ddfcbc22 941 memset(&no_addr, '\0', sizeof(struct IN_ADDR));
62e76326 942
9b7292ce 943 safe_inet_addr("255.255.255.255", &no_addr);
62e76326 944
9b7292ce 945 squid_srandom(time(NULL));
4d64d74a 946
9b7292ce 947 getCurrentTime();
62e76326 948
9b7292ce 949 squid_start = current_time;
62e76326 950
9b7292ce 951 failure_notify = fatal_dump;
4d64d74a 952
6c1962dd 953#if USE_WIN32_SERVICE
954
9b7292ce 955 WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
6c1962dd 956
957#endif
958
9b7292ce 959 mainParseOptions(argc, argv);
4d64d74a 960
6c1962dd 961#if USE_WIN32_SERVICE
962
9b7292ce 963 if (opt_install_service) {
964 WIN32_InstallService();
965 return;
966 }
6c1962dd 967
9b7292ce 968 if (opt_remove_service) {
969 WIN32_RemoveService();
970 return;
971 }
6c1962dd 972
9b7292ce 973 if (opt_command_line) {
974 WIN32_SetServiceCommandLine();
975 return;
976 }
6c1962dd 977
978#endif
979
9b7292ce 980 /* parse configuration file
981 * note: in "normal" case this used to be called from mainInitialize() */
982 {
983 int parse_err;
62e76326 984
9b7292ce 985 if (!ConfigFile)
986 ConfigFile = xstrdup(DefaultConfigFile);
62e76326 987
9b7292ce 988 assert(!configured_once);
62e76326 989
5d620373 990#if USE_LEAKFINDER
62e76326 991
9b7292ce 992 leakInit();
62e76326 993
5d620373 994#endif
8a6218c6 995
9b7292ce 996 Mem::Init();
62e76326 997
9b7292ce 998 cbdataInit();
62e76326 999
9b7292ce 1000 eventInit(); /* eventInit() is required for config parsing */
62e76326 1001
9b7292ce 1002 storeFsInit(); /* required for config parsing */
62e76326 1003
b9ae18aa 1004 /* May not be needed for parsing, have not audited for such */
1005 DiskIOModule::SetupAllModules();
1006
59b2d47f 1007 /* Shouldn't be needed for config parsing, but have not audited for such */
1008 StoreFileSystem::SetupAllFs();
1009
c8f4eac4 1010 /* we may want the parsing process to set this up in the future */
1011 Store::Root(new StoreController);
1012
9b7292ce 1013 parse_err = parseConfigFile(ConfigFile);
62e76326 1014
9b7292ce 1015 if (opt_parse_cfg_only)
6c1962dd 1016#if USE_WIN32_SERVICE
1017
9b7292ce 1018 return;
6c1962dd 1019
1020#else
1021
9b7292ce 1022 return parse_err;
6c1962dd 1023
1024#endif
1025
9b7292ce 1026 }
1027 if (-1 == opt_send_signal)
1028 if (checkRunningPid())
1029 exit(1);
e13ee7ad 1030
9bc73deb 1031#if TEST_ACCESS
62e76326 1032
9b7292ce 1033 comm_init();
62e76326 1034
9b7292ce 1035 comm_select_init();
62e76326 1036
9b7292ce 1037 mainInitialize();
62e76326 1038
9b7292ce 1039 test_access();
62e76326 1040
9b7292ce 1041 return 0;
62e76326 1042
9bc73deb 1043#endif
1044
9b7292ce 1045 /* send signal to running copy and exit */
1046 if (opt_send_signal != -1) {
1047 /* chroot if configured to run inside chroot */
62e76326 1048
9b7292ce 1049 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
1050 fatal("failed to chroot");
1051 }
62e76326 1052
9b7292ce 1053 sendSignal();
1054 /* NOTREACHED */
1055 }
62e76326 1056
9b7292ce 1057 if (opt_create_swap_dirs) {
1058 /* chroot if configured to run inside chroot */
0e657244 1059
9b7292ce 1060 if (Config.chroot_dir && chroot(Config.chroot_dir)) {
1061 fatal("failed to chroot");
1062 }
62e76326 1063
9b7292ce 1064 setEffectiveUser();
1065 debug(0, 0) ("Creating Swap Directories\n");
c8f4eac4 1066 Store::Root().create();
6c1962dd 1067#if USE_WIN32_SERVICE
1068
9b7292ce 1069 return;
6c1962dd 1070#else
1071
9b7292ce 1072 return 0;
6c1962dd 1073#endif
1074
9b7292ce 1075 }
62e76326 1076
9b7292ce 1077 if (!opt_no_daemon)
1078 watch_child(argv);
62e76326 1079
9b7292ce 1080 setMaxFD();
4d64d74a 1081
9b7292ce 1082 /* init comm module */
1083 comm_init();
62e76326 1084
9b7292ce 1085 comm_select_init();
4d64d74a 1086
9b7292ce 1087 if (opt_no_daemon) {
1088 /* we have to init fdstat here. */
1089 fd_open(0, FD_LOG, "stdin");
1090 fd_open(1, FD_LOG, "stdout");
1091 fd_open(2, FD_LOG, "stderr");
1092 }
62e76326 1093
6c1962dd 1094#if USE_WIN32_SERVICE
1095
9b7292ce 1096 WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
6c1962dd 1097
1098#endif
1099
9b7292ce 1100 mainInitialize();
4d64d74a 1101
6c1962dd 1102#if USE_WIN32_SERVICE
1103
9b7292ce 1104 WIN32_svcstatusupdate(SERVICE_RUNNING, 0);
6c1962dd 1105
1106#endif
1107
9b7292ce 1108 /* main loop */
62e76326 1109
9b7292ce 1110 for (;;) {
1111 if (do_reconfigure) {
1112 mainReconfigure();
1113 do_reconfigure = 0;
68aa4272 1114#if defined(_SQUID_MSWIN_) && defined(_DEBUG)
1115
1fa994ac 1116 } else if (do_debug_trap) {
1117 do_debug_trap = 0;
68aa4272 1118 __asm int 3;
1119#endif
1120
9b7292ce 1121 } else if (do_rotate) {
1122 mainRotate();
1123 do_rotate = 0;
1124 } else if (do_shutdown) {
1125 time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
1126 debug(1, 1) ("Preparing for shutdown after %d requests\n",
1127 statCounter.client_http.requests);
1128 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
1129 (int) wait);
1130 do_shutdown = 0;
1131 shutting_down = 1;
6c1962dd 1132#if USE_WIN32_SERVICE
1133
9b7292ce 1134 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);
6c1962dd 1135#endif
1136
9b7292ce 1137 serverConnectionsClose();
9b7292ce 1138 eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
1139 }
62e76326 1140
9b7292ce 1141 eventRun();
1142 int loop_delay = eventNextTime();
62e76326 1143
9b7292ce 1144 if (loop_delay < 0)
1145 loop_delay = 0;
62e76326 1146
9b7292ce 1147 /* Attempt any pending storedir IO */
c8f4eac4 1148 Store::Root().callback();
62e76326 1149
615f9581 1150 comm_calliocallback();
1151
1152 /* and again to deal with indirectly queued events
c2e8186f 1153 * resulting from the first call. These are usually
1154 * callbacks and should be dealt with immediately.
1155 */
d85ff21a 1156 if (comm_iocallbackpending())
c2e8186f 1157 comm_calliocallback();
1158
9b7292ce 1159 switch (comm_select(loop_delay)) {
62e76326 1160
9b7292ce 1161 case COMM_OK:
1162 errcount = 0; /* reset if successful */
1163 break;
62e76326 1164
9b7292ce 1165 case COMM_ERROR:
1166 errcount++;
1167 debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
62e76326 1168
9b7292ce 1169 if (errcount == 10)
1170 fatal_dump("Select Loop failed!");
62e76326 1171
9b7292ce 1172 break;
62e76326 1173
9b7292ce 1174 case COMM_TIMEOUT:
1175 break;
62e76326 1176
9b7292ce 1177 case COMM_SHUTDOWN:
1178 SquidShutdown(NULL);
62e76326 1179
9b7292ce 1180 break;
62e76326 1181
9b7292ce 1182 default:
1183 fatal_dump("MAIN: Internal error -- this should never happen.");
62e76326 1184
9b7292ce 1185 break;
1186 }
090089c4 1187 }
62e76326 1188
9b7292ce 1189 /* NOTREACHED */
6c1962dd 1190#if USE_WIN32_SERVICE
9b7292ce 1191 return;
6c1962dd 1192
1193#else
1194
9b7292ce 1195 return 0;
6c1962dd 1196
1197#endif
090089c4 1198}
7690e8eb 1199
b8d8561b 1200static void
0673c0ba 1201sendSignal(void)
7690e8eb 1202{
ff8d0ea6 1203 pid_t pid;
fedac7e5 1204 debug_log = stderr;
258ac4d7 1205
1206 if (strcmp(Config.pidFilename, "none") == 0) {
1207 debug(0, 1) ("No pid_filename specified. Trusting you know what you are doing.\n");
1208 }
1209
fedac7e5 1210 pid = readPidFile();
62e76326 1211
fedac7e5 1212 if (pid > 1) {
6c1962dd 1213#if USE_WIN32_SERVICE
1214
1215 if (opt_signal_service) {
1216 WIN32_sendSignal(opt_send_signal);
1217 exit(0);
1218 } else
1219#ifdef _SQUID_MSWIN_
1220 {
1221 fprintf(stderr, "%s: ERROR: Could not send ", appname);
1222 fprintf(stderr, "signal to Squid Service:\n");
1223 fprintf(stderr, "missing -n command line switch.\n");
1224 exit(1);
1225 }
1226
1227 /* NOTREACHED */
1228#endif
1229
1230#endif
1231
62e76326 1232 if (kill(pid, opt_send_signal) &&
1233 /* ignore permissions if just running check */
1234 !(opt_send_signal == 0 && errno == EPERM)) {
1235 fprintf(stderr, "%s: ERROR: Could not send ", appname);
1236 fprintf(stderr, "signal %d to process %d: %s\n",
1237 opt_send_signal, (int) pid, xstrerror());
1238 exit(1);
1239 }
fedac7e5 1240 } else {
62e76326 1241 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
1242 exit(1);
7690e8eb 1243 }
62e76326 1244
fedac7e5 1245 /* signal successfully sent */
1246 exit(0);
1247}
f95b8144 1248
a50bfe93 1249#ifndef _SQUID_MSWIN_
e18d7fdc 1250/*
1251 * This function is run when Squid is in daemon mode, just
1252 * before the parent forks and starts up the child process.
1253 * It can be used for admin-specific tasks, such as notifying
1254 * someone that Squid is (re)started.
1255 */
1256static void
1257mainStartScript(const char *prog)
1258{
1259 char script[SQUID_MAXPATHLEN];
1260 char *t;
1261 size_t sl = 0;
1262 pid_t cpid;
1263 pid_t rpid;
1264 xstrncpy(script, prog, MAXPATHLEN);
62e76326 1265
e18d7fdc 1266 if ((t = strrchr(script, '/'))) {
62e76326 1267 *(++t) = '\0';
1268 sl = strlen(script);
e18d7fdc 1269 }
62e76326 1270
e18d7fdc 1271 xstrncpy(&script[sl], squid_start_script, MAXPATHLEN - sl);
62e76326 1272
e18d7fdc 1273 if ((cpid = fork()) == 0) {
62e76326 1274 /* child */
482aa790 1275 execl(script, squid_start_script, NULL);
1276 _exit(-1);
e18d7fdc 1277 } else {
62e76326 1278 do {
e18d7fdc 1279#ifdef _SQUID_NEXT_
62e76326 1280 union wait status;
1281 rpid = wait3(&status, 0, NULL);
e18d7fdc 1282#else
62e76326 1283
1284 int status;
1285 rpid = waitpid(-1, &status, 0);
e18d7fdc 1286#endif
62e76326 1287
1288 } while (rpid != cpid);
e18d7fdc 1289 }
1290}
1291
a50bfe93 1292#endif /* _SQUID_MSWIN_ */
1293
efd900cb 1294static int
1295checkRunningPid(void)
1296{
1297 pid_t pid;
e0077312 1298
1299 if (!debug_log)
1300 debug_log = stderr;
1301
efd900cb 1302 pid = readPidFile();
62e76326 1303
efd900cb 1304 if (pid < 2)
62e76326 1305 return 0;
1306
efd900cb 1307 if (kill(pid, 0) < 0)
62e76326 1308 return 0;
1309
cb7a4fcb 1310 debugs(0, 0, "Squid is already running! Process ID " << pid);
62e76326 1311
efd900cb 1312 return 1;
1313}
1314
f95b8144 1315static void
bbe199dc 1316watch_child(char *argv[])
f95b8144 1317{
a50bfe93 1318#ifndef _SQUID_MSWIN_
f95b8144 1319 char *prog;
f95b8144 1320 int failcount = 0;
1321 time_t start;
1322 time_t stop;
1323#ifdef _SQUID_NEXT_
62e76326 1324
f95b8144 1325 union wait status;
1326#else
62e76326 1327
f95b8144 1328 int status;
1329#endif
62e76326 1330
e3a3b845 1331 pid_t pid;
c99c5397 1332#ifdef TIOCNOTTY
1333
54f742e7 1334 int i;
c99c5397 1335#endif
1336
742724a4 1337 int nullfd;
62e76326 1338
f95b8144 1339 if (*(argv[0]) == '(')
62e76326 1340 return;
1341
54f742e7 1342 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
62e76326 1343
54f742e7 1344 if ((pid = fork()) < 0)
62e76326 1345 syslog(LOG_ALERT, "fork failed: %s", xstrerror());
54f742e7 1346 else if (pid > 0)
62e76326 1347 exit(0);
1348
54f742e7 1349 if (setsid() < 0)
62e76326 1350 syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
1351
efd900cb 1352 closelog();
62e76326 1353
54f742e7 1354#ifdef TIOCNOTTY
62e76326 1355
c4aefe96 1356 if ((i = open("/dev/tty", O_RDWR | O_TEXT)) >= 0) {
62e76326 1357 ioctl(i, TIOCNOTTY, NULL);
1358 close(i);
54f742e7 1359 }
62e76326 1360
54f742e7 1361#endif
b05490a8 1362
1363
7f6ffd15 1364 /*
1365 * RBCOLLINS - if cygwin stackdumps when squid is run without
1366 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1367 * 1.1.3. execvp had a bit overflow error in a loop..
1368 */
742724a4 1369 /* Connect stdio to /dev/null in daemon mode */
c4aefe96 1370 nullfd = open("/dev/null", O_RDWR | O_TEXT);
62e76326 1371
e4a1325e 1372 if (nullfd < 0)
1373 fatalf("/dev/null: %s\n", xstrerror());
1374
742724a4 1375 dup2(nullfd, 0);
62e76326 1376
742724a4 1377 if (opt_debug_stderr < 0) {
62e76326 1378 dup2(nullfd, 1);
1379 dup2(nullfd, 2);
742724a4 1380 }
62e76326 1381
f95b8144 1382 for (;;) {
62e76326 1383 mainStartScript(argv[0]);
1384
1385 if ((pid = fork()) == 0) {
1386 /* child */
1387 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1388 prog = xstrdup(argv[0]);
1389 argv[0] = xstrdup("(squid)");
1390 execvp(prog, argv);
1391 syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
1392 }
1393
1394 /* parent */
1395 openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
1396
1397 syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
1398
1399 time(&start);
1400
1401 squid_signal(SIGINT, SIG_IGN, SA_RESTART);
1402
f95b8144 1403#ifdef _SQUID_NEXT_
62e76326 1404
1405 pid = wait3(&status, 0, NULL);
1406
f95b8144 1407#else
62e76326 1408
1409 pid = waitpid(-1, &status, 0);
1410
1411#endif
1412
1413 time(&stop);
1414
1415 if (WIFEXITED(status)) {
1416 syslog(LOG_NOTICE,
1417 "Squid Parent: child process %d exited with status %d",
1418 pid, WEXITSTATUS(status));
1419 } else if (WIFSIGNALED(status)) {
1420 syslog(LOG_NOTICE,
1421 "Squid Parent: child process %d exited due to signal %d",
1422 pid, WTERMSIG(status));
1423 } else {
1424 syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
1425 }
1426
1427 if (stop - start < 10)
1428 failcount++;
1429 else
1430 failcount = 0;
1431
1432 if (failcount == 5) {
1433 syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
1434 exit(1);
1435 }
1436
1437 if (WIFEXITED(status))
1438 if (WEXITSTATUS(status) == 0)
1439 exit(0);
1440
1441 if (WIFSIGNALED(status)) {
1442 switch (WTERMSIG(status)) {
1443
1444 case SIGKILL:
1445 exit(0);
1446 break;
1447
1448 default:
1449 break;
1450 }
1451 }
1452
1453 squid_signal(SIGINT, SIG_DFL, SA_RESTART);
1454 sleep(3);
f95b8144 1455 }
62e76326 1456
bbe199dc 1457 /* NOTREACHED */
a50bfe93 1458#endif /* _SQUID_MSWIN_ */
f95b8144 1459}
fff6ad65 1460
9ec1a1dc 1461static void
d723bf6b 1462SquidShutdown(void *unused)
fff6ad65 1463{
6c1962dd 1464#if USE_WIN32_SERVICE
1465 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
1466#endif
1467
fff6ad65 1468 debug(1, 1) ("Shutting down...\n");
95a83c22 1469#if USE_DNSSERVERS
1470
1471 dnsShutdown();
1472#else
1473
1474 idnsShutdown();
1475#endif
1476
1477 redirectShutdown();
1478 externalAclShutdown();
d723bf6b 1479 icpConnectionClose();
1480#if USE_HTCP
62e76326 1481
d723bf6b 1482 htcpSocketClose();
1483#endif
1484#ifdef SQUID_SNMP
62e76326 1485
d723bf6b 1486 snmpConnectionClose();
320e9f36 1487#endif
eb824054 1488#if USE_WCCP
62e76326 1489
320e9f36 1490 wccpConnectionClose();
d723bf6b 1491#endif
62e76326 1492
fff6ad65 1493 releaseServerSockets();
d723bf6b 1494 commCloseAllSockets();
515ec4dc 1495#if DELAY_POOLS
62e76326 1496
b67e2c8c 1497 DelayPools::FreePools();
515ec4dc 1498#endif
62e76326 1499
5dae8514 1500 authenticateShutdown();
a3d0a19d 1501#if USE_UNLINKD
62e76326 1502
fff6ad65 1503 unlinkdClose();
a3d0a19d 1504#endif
6c1962dd 1505#if USE_WIN32_SERVICE
1506
1507 WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
1508#endif
62e76326 1509
c8f4eac4 1510 Store::Root().sync(); /* Flush pending object writes/unlinks */
fff6ad65 1511 storeDirWriteCleanLogs(0);
1512 PrintRusage();
1513 dumpMallocStats();
c8f4eac4 1514 Store::Root().sync(); /* Flush log writes */
fff6ad65 1515 storeLogClose();
1516 accessLogClose();
5b824235 1517 useragentLogClose();
c9b99797 1518 refererCloseLog();
225644d7 1519#if WIP_FWD_LOG
62e76326 1520
225644d7 1521 fwdUninit();
1522#endif
62e76326 1523
c8f4eac4 1524 Store::Root().sync(); /* Flush log close */
59b2d47f 1525 StoreFileSystem::FreeAllFs();
b9ae18aa 1526 DiskIOModule::FreeAllModules();
33ab18e8 1527#if PURIFY || XMALLOC_TRACE
62e76326 1528
fff6ad65 1529 configFreeMemory();
1530 storeFreeMemory();
33ab18e8 1531 /*stmemFreeMemory(); */
fff6ad65 1532 netdbFreeMemory();
1533 ipcacheFreeMemory();
1534 fqdncacheFreeMemory();
1535 asnFreeMemory();
26a369ba 1536 clientdbFreeMemory();
7021844c 1537 httpHeaderCleanModule();
d2db411c 1538 statFreeMemory();
f1fc2a8d 1539 eventFreeMemory();
c68e9c6b 1540 mimeFreeMemory();
1541 errorClean();
fff6ad65 1542#endif
26a369ba 1543#if !XMALLOC_TRACE
62e76326 1544
54f742e7 1545 if (opt_no_daemon) {
62e76326 1546 file_close(0);
1547 file_close(1);
1548 file_close(2);
54f742e7 1549 }
62e76326 1550
33ab18e8 1551#endif
fff6ad65 1552 fdDumpOpen();
62e76326 1553
fff6ad65 1554 fdFreeMemory();
62e76326 1555
ddb43c58 1556 memClean();
62e76326 1557
33ab18e8 1558#if XMALLOC_TRACE
62e76326 1559
26a369ba 1560 xmalloc_find_leaks();
62e76326 1561
26a369ba 1562 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
62e76326 1563
33ab18e8 1564#endif
36a97e19 1565#if MEM_GEN_TRACE
62e76326 1566
399e85ea 1567 log_trace_done();
62e76326 1568
36a97e19 1569#endif
62e76326 1570
ab50ee9e 1571 if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) {
62e76326 1572 enter_suid();
1573 safeunlink(Config.pidFilename, 0);
1574 leave_suid();
ab50ee9e 1575 }
62e76326 1576
a60f7062 1577 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
62e76326 1578 version_string);
1579
7e3ce7b9 1580 if (debug_log)
62e76326 1581 fclose(debug_log);
1582
fff6ad65 1583 exit(0);
1584}