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