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