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