]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
compare lastref to e->lastref during store rebuild. Might regret this
[thirdparty/squid.git] / src / main.cc
CommitLineData
a47b9029 1
30a4f2a8 2/*
a8e69881 3 * $Id: main.cc,v 1.184 1997/10/30 20:38:16 wessels Exp $
30a4f2a8 4 *
5 * DEBUG: section 1 Startup and Main Loop
6 * AUTHOR: Harvest Derived
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
30a4f2a8 9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32/*
33 * Copyright (c) 1994, 1995. All rights reserved.
34 *
35 * The Harvest software was developed by the Internet Research Task
36 * Force Research Group on Resource Discovery (IRTF-RD):
37 *
38 * Mic Bowman of Transarc Corporation.
39 * Peter Danzig of the University of Southern California.
40 * Darren R. Hardy of the University of Colorado at Boulder.
41 * Udi Manber of the University of Arizona.
42 * Michael F. Schwartz of the University of Colorado at Boulder.
43 * Duane Wessels of the University of Colorado at Boulder.
44 *
45 * This copyright notice applies to software in the Harvest
46 * ``src/'' directory only. Users should consult the individual
47 * copyright notices in the ``components/'' subdirectories for
48 * copyright information about other software bundled with the
49 * Harvest source code distribution.
50 *
51 * TERMS OF USE
52 *
53 * The Harvest software may be used and re-distributed without
54 * charge, provided that the software origin and research team are
55 * cited in any use of the system. Most commonly this is
56 * accomplished by including a link to the Harvest Home Page
57 * (http://harvest.cs.colorado.edu/) from the query page of any
58 * Broker you deploy, as well as in the query result pages. These
59 * links are generated automatically by the standard Broker
60 * software distribution.
61 *
62 * The Harvest software is provided ``as is'', without express or
63 * implied warranty, and with no support nor obligation to assist
64 * in its use, correction, modification or enhancement. We assume
65 * no liability with respect to the infringement of copyrights,
66 * trade secrets, or any patents, and are not responsible for
67 * consequential damages. Proper use of the Harvest software is
68 * entirely the responsibility of the user.
69 *
70 * DERIVATIVE WORKS
71 *
72 * Users may make derivative works from the Harvest software, subject
73 * to the following constraints:
74 *
75 * - You must include the above copyright notice and these
76 * accompanying paragraphs in all forms of derivative works,
77 * and any documentation and other materials related to such
78 * distribution and use acknowledge that the software was
79 * developed at the above institutions.
80 *
81 * - You must notify IRTF-RD regarding your distribution of
82 * the derivative work.
83 *
84 * - You must clearly notify users that your are distributing
85 * a modified version and not the original Harvest software.
86 *
87 * - Any derivative product is also subject to these copyright
88 * and use restrictions.
89 *
90 * Note that the Harvest software is NOT in the public domain. We
91 * retain copyright, as specified above.
92 *
93 * HISTORY OF FREE SOFTWARE STATUS
94 *
95 * Originally we required sites to license the software in cases
96 * where they were going to build commercial products/services
97 * around Harvest. In June 1995 we changed this policy. We now
98 * allow people to use the core Harvest software (the code found in
99 * the Harvest ``src/'' directory) for free. We made this change
100 * in the interest of encouraging the widest possible deployment of
101 * the technology. The Harvest software is really a reference
102 * implementation of a set of protocols and formats, some of which
103 * we intend to standardize. We encourage commercial
104 * re-implementations of code complying to this set of standards.
105 */
44a47c6e 106
107#include "squid.h"
108
30a4f2a8 109/* for error reporting from xmalloc and friends */
ea3a2a69 110extern void (*failure_notify) (const char *);
30a4f2a8 111
f1dc9b30 112static int opt_send_signal = -1;
f95b8144 113static int opt_no_daemon = 0;
67508012 114static volatile int rotate_pending = 0; /* set by SIGUSR1 handler */
30a4f2a8 115static int httpPortNumOverride = 1;
116static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
117#if MALLOC_DBG
4d64d74a 118static int malloc_debug_level = 0;
30a4f2a8 119#endif
4d7add01 120
b984c445 121static SIGHDLR rotate_logs;
122static SIGHDLR reconfigure;
123#if ALARM_UPDATES_TIME
124static SIGHDLR time_tick;
125#endif
f5b8bbc4 126static void mainInitialize(void);
127static void mainReconfigure(void);
128static void usage(void);
129static void mainParseOptions(int, char **);
130static void sendSignal(void);
131static void serverConnectionsOpen(void);
bbe199dc 132static void watch_child(char **);
b8d8561b 133
134static void
0673c0ba 135usage(void)
ccff9601 136{
0ee4272b 137 fprintf(stderr,
78f1250a 138 "Usage: %s [-svzCDFRUVY] [-f config-file] [-[au] port] [-k signal]\n"
0ee4272b 139 " -a port Specify ASCII port number (default: %d).\n"
0d90407c 140 " -d Write debugging to stderr also.\n"
0ee4272b 141 " -f file Use given config-file instead of\n"
142 " %s\n"
143 " -h Print help message.\n"
0ee4272b 144 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check\n"
145 " Send signal to running copy and exit.\n"
146 " -s Enable logging to syslog.\n"
147 " -u port Specify ICP port number (default: %d), disable with 0.\n"
148 " -v Print version.\n"
149 " -z Zap disk storage -- deletes all objects in disk cache.\n"
150 " -C Do not catch fatal signals.\n"
151 " -D Disable initial DNS tests.\n"
152 " -F Foreground fast store rebuild.\n"
153 " -R Do not set REUSEADDR on port.\n"
154 " -U Unlink expired objects on reload.\n"
155 " -V Virtual host httpd-accelerator.\n"
429fdbec 156 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
30a4f2a8 157 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 158 exit(1);
ccff9601 159}
160
b8d8561b 161static void
162mainParseOptions(int argc, char *argv[])
090089c4 163{
090089c4 164 extern char *optarg;
4d64d74a 165 int c;
090089c4 166
f95b8144 167 while ((c = getopt(argc, argv, "CDFNRVYXa:bdf:hk:m:su:vz?")) != -1) {
090089c4 168 switch (c) {
090089c4 169 case 'C':
1758c627 170 opt_catch_signals = 0;
090089c4 171 break;
172 case 'D':
30a4f2a8 173 opt_dns_tests = 0;
090089c4 174 break;
30a4f2a8 175 case 'F':
176 opt_foreground_rebuild = 1;
090089c4 177 break;
f95b8144 178 case 'N':
179 opt_no_daemon = 1;
090089c4 180 case 'R':
181 do_reuse = 0;
182 break;
30a4f2a8 183 case 'V':
184 vhost_mode = 1;
185 break;
e924600d 186 case 'X':
187 /* force full debugging */
188 sigusr2_handle(SIGUSR2);
189 break;
30a4f2a8 190 case 'Y':
191 opt_reload_hit_only = 1;
192 break;
193 case 'a':
194 httpPortNumOverride = atoi(optarg);
195 break;
0d90407c 196 case 'd':
197 opt_debug_stderr = 1;
198 break;
090089c4 199 case 'f':
00fac1f8 200 xfree(ConfigFile);
201 ConfigFile = xstrdup(optarg);
090089c4 202 break;
30a4f2a8 203 case 'h':
204 usage();
090089c4 205 break;
7690e8eb 206 case 'k':
24382924 207 if ((int) strlen(optarg) < 1)
7690e8eb 208 usage();
209 if (!strncmp(optarg, "reconfigure", strlen(optarg)))
210 opt_send_signal = SIGHUP;
211 else if (!strncmp(optarg, "rotate", strlen(optarg)))
212 opt_send_signal = SIGUSR1;
213 else if (!strncmp(optarg, "debug", strlen(optarg)))
214 opt_send_signal = SIGUSR2;
215 else if (!strncmp(optarg, "shutdown", strlen(optarg)))
216 opt_send_signal = SIGTERM;
6759a5fb 217 else if (!strncmp(optarg, "interrupt", strlen(optarg)))
218 opt_send_signal = SIGINT;
7690e8eb 219 else if (!strncmp(optarg, "kill", strlen(optarg)))
220 opt_send_signal = SIGKILL;
221 else if (!strncmp(optarg, "check", strlen(optarg)))
fedac7e5 222 opt_send_signal = 0; /* SIGNULL */
7690e8eb 223 else
224 usage();
225 break;
090089c4 226 case 'm':
30a4f2a8 227#if MALLOC_DBG
090089c4 228 malloc_debug_level = atoi(optarg);
34c54bb6 229 /* NOTREACHED */
090089c4 230 break;
30a4f2a8 231#else
232 fatal("Need to add -DMALLOC_DBG when compiling to use -m option");
24382924 233 /* NOTREACHED */
30a4f2a8 234#endif
235 case 's':
6e40f263 236 opt_syslog_enable = 1;
30a4f2a8 237 break;
238 case 'u':
239 icpPortNumOverride = atoi(optarg);
240 if (icpPortNumOverride < 0)
241 icpPortNumOverride = 0;
242 break;
243 case 'v':
244 printf("Squid Cache: Version %s\n", version_string);
245 exit(0);
246 /* NOTREACHED */
090089c4 247 case 'z':
b6f794d6 248 opt_zap_disk_store = 1;
090089c4 249 break;
250 case '?':
090089c4 251 default:
ccff9601 252 usage();
090089c4 253 break;
254 }
090089c4 255 }
4d64d74a 256}
090089c4 257
b8d8561b 258static void
259rotate_logs(int sig)
30a4f2a8 260{
a3d5953d 261 debug(1, 1) ("rotate_logs: SIGUSR1 received.\n");
30a4f2a8 262 rotate_pending = 1;
263#if !HAVE_SIGACTION
264 signal(sig, rotate_logs);
265#endif
266}
267
b984c445 268#if ALARM_UPDATES_TIME
97c03d3c 269static void
270time_tick(int sig)
271{
272 getCurrentTime();
273 alarm(1);
274#if !HAVE_SIGACTION
275 signal(sig, time_tick);
276#endif
277}
38d04788 278
b984c445 279#endif
97c03d3c 280
b8d8561b 281static void
282reconfigure(int sig)
30a4f2a8 283{
dbe4fd8e 284 reconfigure_pending = 1;
30a4f2a8 285#if !HAVE_SIGACTION
286 signal(sig, reconfigure);
287#endif
288}
289
b8d8561b 290void
291shut_down(int sig)
30a4f2a8 292{
f3753518 293 shutdown_pending = sig == SIGINT ? -1 : 1;
a3d5953d 294 debug(1, 1) ("Preparing for shutdown after %d connections\n",
30a4f2a8 295 ntcpconn + nudpconn);
a3d5953d 296 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
5c5783a2 297 shutdown_pending > 0 ? Config.shutdownLifetime : 0);
cadc2d55 298#ifdef KILL_PARENT_OPT
88738790 299 {
300 pid_t ppid = getppid();
301 if (ppid > 1) {
302 debug(1, 1, "Killing RunCache, pid %d\n", ppid);
303 kill(ppid, sig);
304 }
305 }
cadc2d55 306#endif
6e40f263 307#if SA_RESETHAND == 0
308 signal(SIGTERM, SIG_DFL);
309 signal(SIGINT, SIG_DFL);
310#endif
30a4f2a8 311}
312
24382924 313static void
0673c0ba 314serverConnectionsOpen(void)
4d64d74a 315{
30a4f2a8 316 struct in_addr addr;
651ca9d8 317 struct sockaddr_in xaddr;
30a4f2a8 318 u_short port;
270b86af 319 ushortlist *u;
48f44632 320 int len;
321 int x;
812ed90c 322 int fd;
edeb28fd 323 wordlist *s;
a47b9029 324 for (u = Config.Port.http; u; u = u->next) {
0d90407c 325 enter_suid();
326 fd = comm_open(SOCK_STREAM,
812ed90c 327 0,
328 Config.Addrs.tcp_incoming,
270b86af 329 u->i,
812ed90c 330 COMM_NONBLOCKING,
331 "HTTP Socket");
0d90407c 332 leave_suid();
812ed90c 333 if (fd < 0)
0d90407c 334 continue;
335 comm_listen(fd);
336 commSetSelect(fd, COMM_SELECT_READ, httpAccept, NULL, 0);
70a9dab4 337 commSetDefer(fd, httpAcceptDefer, NULL);
a3d5953d 338 debug(1, 1) ("Accepting HTTP connections on port %d, FD %d.\n",
270b86af 339 (int) u->i, fd);
812ed90c 340 HttpSockets[NHttpSockets++] = fd;
090089c4 341 }
812ed90c 342 if (NHttpSockets < 1)
343 fatal("Cannot open HTTP Port");
17a0a4ee 344 if (!Config2.Accel.on || Config.onoff.accel_with_proxy) {
7690e8eb 345 if ((port = Config.Port.icp) > (u_short) 0) {
328d1c43 346 enter_suid();
16b204c4 347 theInIcpConnection = comm_open(SOCK_DGRAM,
348 0,
b6f794d6 349 Config.Addrs.udp_incoming,
30a4f2a8 350 port,
16b204c4 351 COMM_NONBLOCKING,
30a4f2a8 352 "ICP Port");
328d1c43 353 leave_suid();
30a4f2a8 354 if (theInIcpConnection < 0)
355 fatal("Cannot open ICP Port");
356 fd_note(theInIcpConnection, "ICP socket");
b177367b 357 commSetSelect(theInIcpConnection,
090089c4 358 COMM_SELECT_READ,
359 icpHandleUdp,
b177367b 360 NULL, 0);
edeb28fd 361 for (s = Config.mcast_group_list; s; s = s->next)
8407afee 362 ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
a3d5953d 363 debug(1, 1) ("Accepting ICP connections on port %d, FD %d.\n",
f990cccc 364 (int) port, theInIcpConnection);
30a4f2a8 365
429fdbec 366 if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) {
328d1c43 367 enter_suid();
16b204c4 368 theOutIcpConnection = comm_open(SOCK_DGRAM,
cc6a9d2e 369 0,
30a4f2a8 370 addr,
371 port,
cc6a9d2e 372 COMM_NONBLOCKING,
30a4f2a8 373 "ICP Port");
9d90e665 374 leave_suid();
30a4f2a8 375 if (theOutIcpConnection < 0)
376 fatal("Cannot open Outgoing ICP Port");
b177367b 377 commSetSelect(theOutIcpConnection,
30a4f2a8 378 COMM_SELECT_READ,
379 icpHandleUdp,
b177367b 380 NULL, 0);
a3d5953d 381 debug(1, 1) ("Accepting ICP connections on port %d, FD %d.\n",
0d90407c 382 (int) port, theInIcpConnection);
30a4f2a8 383 fd_note(theOutIcpConnection, "Outgoing ICP socket");
384 fd_note(theInIcpConnection, "Incoming ICP socket");
385 } else {
386 theOutIcpConnection = theInIcpConnection;
387 }
651ca9d8 388 memset(&theOutICPAddr, '\0', sizeof(struct in_addr));
48f44632 389 len = sizeof(struct sockaddr_in);
651ca9d8 390 memset(&xaddr, '\0', len);
48f44632 391 x = getsockname(theOutIcpConnection,
651ca9d8 392 (struct sockaddr *) &xaddr, &len);
48f44632 393 if (x < 0)
a3d5953d 394 debug(50, 1) ("theOutIcpConnection FD %d: getsockname: %s\n",
48f44632 395 theOutIcpConnection, xstrerror());
651ca9d8 396 else
397 theOutICPAddr = xaddr.sin_addr;
090089c4 398 }
399 }
678c6099 400#ifdef SQUID_SNMP
6a54c60e 401 if (Config.Port.snmp) {
402 enter_suid();
403 fd = comm_open(SOCK_STREAM,
404 0,
405 Config.Addrs.snmp_incoming,
406 SQUID_SNMP_PORT,
407 COMM_NONBLOCKING,
408 "SNMP Socket");
409 leave_suid();
410 if (fd < 0)
411 continue;
412 comm_listen(fd);
413 commSetSelect(fd, COMM_SELECT_READ, snmpAccept, NULL, 0);
414 debug(1, 1) ("Accepting SNMP connections on port %d, FD %d.\n",
415 (int) SQUID_SNMP_PORT, fd);
678c6099 416 }
417#endif /* SQUID_SNMP */
418
419
5ecceaa4 420 clientdbInit();
16b204c4 421 icmpOpen();
67508012 422 netdbInit();
85034133 423 peerSelectInit();
5f3f8d0e 424}
425
b8d8561b 426void
0673c0ba 427serverConnectionsClose(void)
5f3f8d0e 428{
30a4f2a8 429 /* NOTE, this function will be called repeatedly while shutdown
430 * is pending */
812ed90c 431 int i;
0d90407c 432 for (i = 0; i < NHttpSockets; i++) {
433 if (HttpSockets[i] >= 0) {
a3d5953d 434 debug(1, 1) ("FD %d Closing HTTP connection\n", HttpSockets[i]);
812ed90c 435 comm_close(HttpSockets[i]);
812ed90c 436 HttpSockets[i] = -1;
437 }
090089c4 438 }
0d90407c 439 NHttpSockets = 0;
30a4f2a8 440 if (theInIcpConnection >= 0) {
441 /* NOTE, don't close outgoing ICP connection, we need to write to
442 * it during shutdown */
a3d5953d 443 debug(1, 1) ("FD %d Closing ICP connection\n",
30a4f2a8 444 theInIcpConnection);
445 if (theInIcpConnection != theOutIcpConnection)
446 comm_close(theInIcpConnection);
88738790 447 else
448 commSetSelect(theInIcpConnection,
30a4f2a8 449 COMM_SELECT_READ,
450 NULL,
88738790 451 NULL,
452 0);
30a4f2a8 453 theInIcpConnection = -1;
5f3f8d0e 454 }
c7433536 455 if (icmp_sock > -1)
f6610c4e 456 icmpClose();
5f3f8d0e 457}
458
b8d8561b 459static void
dbe4fd8e 460mainReconfigure(void)
5f3f8d0e 461{
a3d5953d 462 debug(1, 0) ("Restarting Squid Cache (version %s)...\n", version_string);
0ffd22bc 463 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
00fac1f8 464 parseConfigFile(ConfigFile);
b6f794d6 465 _db_init(Config.Log.log, Config.debugOptions);
429fdbec 466 ipcache_restart(); /* clear stuck entries */
467 fqdncache_restart(); /* sigh, fqdncache too */
f88bb09c 468 dnsOpenServers();
d2af9477 469 redirectOpenServers();
0ffd22bc 470 serverConnectionsOpen();
17a0a4ee 471 if (theOutIcpConnection >= 0 && (!Config2.Accel.on || Config.onoff.accel_with_proxy))
30a4f2a8 472 neighbors_open(theOutIcpConnection);
a3d5953d 473 debug(1, 0) ("Ready to serve requests.\n");
5f3f8d0e 474}
475
b8d8561b 476static void
0673c0ba 477mainInitialize(void)
5f3f8d0e 478{
1758c627 479 if (opt_catch_signals) {
30a4f2a8 480 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
481 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 482 }
30a4f2a8 483 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
484 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
44f99671 485
8407afee 486 if (!configured_once)
487 cbdataInit();
00fac1f8 488 if (ConfigFile == NULL)
489 ConfigFile = xstrdup(DefaultConfigFile);
490 parseConfigFile(ConfigFile);
5f3f8d0e 491
30a4f2a8 492 leave_suid(); /* Run as non privilegied user */
d41a5e15 493 if (geteuid() == 0) {
a3d5953d 494 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
495 debug(0, 0) ("start Squid as root, then you must configure\n");
496 debug(0, 0) ("it to run as a non-priveledged user with the\n");
497 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
d41a5e15 498 fatal("Don't run Squid as root, set 'cache_effective_user'!");
499 }
270b86af 500 assert(Config.Port.http);
30a4f2a8 501 if (httpPortNumOverride != 1)
270b86af 502 Config.Port.http->i = (u_short) httpPortNumOverride;
30a4f2a8 503 if (icpPortNumOverride != 1)
f2052513 504 Config.Port.icp = (u_short) icpPortNumOverride;
30a4f2a8 505
b6f794d6 506 _db_init(Config.Log.log, Config.debugOptions);
5c5783a2 507 fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
5f3f8d0e 508
a3d5953d 509 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
30a4f2a8 510 version_string,
511 CONFIG_HOST_TYPE);
70364f29 512 debug(1, 0) ("Process ID %d\n", (int) getpid());
a3d5953d 513 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
5f3f8d0e 514
dbe4fd8e 515 if (!configured_once) {
94e891ea 516 stmemInit(); /* stmem must go before at least redirect */
234967c9 517 disk_init(); /* disk_init must go before ipcache_init() */
850c4ead 518 }
5f3f8d0e 519 ipcache_init();
f88bb09c 520 fqdncache_init();
521 dnsOpenServers();
d2af9477 522 redirectOpenServers();
b012353a 523 useragentOpenLog();
9b312a19 524 errorInitialize();
5f3f8d0e 525
30a4f2a8 526#if MALLOC_DBG
5f3f8d0e 527 malloc_debug(0, malloc_debug_level);
528#endif
529
dbe4fd8e 530 if (!configured_once) {
429fdbec 531 unlinkdInit();
5f3f8d0e 532 /* module initialization */
7111c86a 533 urlInitialize();
a528eb87 534 stat_init(&HTTPCacheInfo, Config.Log.access);
535 stat_init(&ICPCacheInfo, NULL);
6605655c 536 objcacheInit();
5f3f8d0e 537 storeInit();
090089c4 538
b6f794d6 539 if (Config.effectiveUser) {
234967c9 540 /* we were probably started as root, so cd to a swap
541 * directory in case we dump core */
641941c0 542 if (chdir(storeSwapDir(0)) < 0) {
a3d5953d 543 debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror());
234967c9 544 fatal_dump("Cannot cd to swap directory?");
545 }
546 }
5f3f8d0e 547 /* after this point we want to see the mallinfo() output */
548 do_mallinfo = 1;
812ed90c 549 mimeInit(Config.mimeTablePathname);
603a02fd 550 pconnInit();
5f3f8d0e 551 }
2285407f 552 serverConnectionsOpen();
17a0a4ee 553 if (theOutIcpConnection >= 0 && (!Config2.Accel.on || Config.onoff.accel_with_proxy))
30a4f2a8 554 neighbors_open(theOutIcpConnection);
555
dbe4fd8e 556 if (!configured_once)
0a5b9b32 557 writePidFile(); /* write PID file */
558
30a4f2a8 559 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
560 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
561 squid_signal(SIGHUP, reconfigure, SA_RESTART);
562 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
563 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
b984c445 564#if ALARM_UPDATES_TIME
97c03d3c 565 squid_signal(SIGALRM, time_tick, SA_RESTART);
566 alarm(1);
b984c445 567#endif
a3d5953d 568 debug(1, 0) ("Ready to serve requests.\n");
4d7add01 569
dbe4fd8e 570 if (!configured_once) {
48f44632 571 eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1);
572 eventAdd("storeDirClean", storeDirClean, NULL, 15);
17a0a4ee 573 if (Config.onoff.announce)
e924600d 574 eventAdd("start_announce", start_announce, NULL, 3600);
582b6456 575 eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10);
4d7add01 576 }
dbe4fd8e 577 configured_once = 1;
4d64d74a 578}
579
b8d8561b 580int
581main(int argc, char **argv)
4d64d74a 582{
583 int errcount = 0;
4d64d74a 584 int n; /* # of GC'd objects */
bc528c78 585 time_t loop_delay;
4d64d74a 586
88738790 587 debug_log = stderr;
e83892e9 588 if (FD_SETSIZE < Squid_MaxFD)
589 Squid_MaxFD = FD_SETSIZE;
590
7328e889 591 /* call mallopt() before anything else */
0b29fe44 592#if HAVE_MALLOPT
7328e889 593#ifdef M_GRAIN
594 /* Round up all sizes to a multiple of this */
595 mallopt(M_GRAIN, 16);
596#endif
597#ifdef M_MXFAST
598 /* biggest size that is considered a small block */
599 mallopt(M_MXFAST, 256);
600#endif
601#ifdef M_NBLKS
602 /* allocate this many small blocks at once */
603 mallopt(M_NLBLKS, 32);
604#endif
605#endif /* HAVE_MALLOPT */
606
30a4f2a8 607 memset(&local_addr, '\0', sizeof(struct in_addr));
429fdbec 608 safe_inet_addr(localhost, &local_addr);
28070024 609 memset(&any_addr, '\0', sizeof(struct in_addr));
429fdbec 610 safe_inet_addr("0.0.0.0", &any_addr);
28070024 611 memset(&no_addr, '\0', sizeof(struct in_addr));
429fdbec 612 safe_inet_addr("255.255.255.255", &no_addr);
88738790 613 squid_srandom(time(NULL));
4d64d74a 614
b8de7ebe 615 squid_starttime = getCurrentTime();
4d64d74a 616 failure_notify = fatal_dump;
617
618 mainParseOptions(argc, argv);
619
7690e8eb 620 /* send signal to running copy and exit */
621 if (opt_send_signal != -1) {
622 sendSignal();
623 /* NOTREACHED */
624 }
f95b8144 625 if (!opt_no_daemon)
bbe199dc 626 watch_child(argv);
4d64d74a 627 setMaxFD();
628
1758c627 629 if (opt_catch_signals)
e83892e9 630 for (n = Squid_MaxFD; n > 2; n--)
30a4f2a8 631 close(n);
4d64d74a 632
4d64d74a 633 /*init comm module */
634 comm_init();
635
636 /* we have to init fdstat here. */
429fdbec 637 fdstat_init();
5c5783a2 638 fd_open(0, FD_LOG, "stdin");
639 fd_open(1, FD_LOG, "stdout");
640 fd_open(2, FD_LOG, "stderr");
4d64d74a 641
4d64d74a 642 mainInitialize();
643
090089c4 644 /* main loop */
983061ed 645 for (;;) {
30a4f2a8 646 if (rotate_pending) {
e97f40f4 647 icmpClose();
30a4f2a8 648 _db_rotate_log(); /* cache.log */
e102ebda 649 storeWriteCleanLogs(1);
30a4f2a8 650 storeRotateLog(); /* store.log */
a4394ebd 651 accessLogRotate(); /* access.log */
b012353a 652 useragentRotateLog(); /* useragent.log */
e97f40f4 653 icmpOpen();
30a4f2a8 654 rotate_pending = 0;
655 }
48f44632 656 eventRun();
657 if ((loop_delay = eventNextTime()) < 0)
4d7add01 658 loop_delay = 0;
812ed90c 659#if HAVE_POLL
660 switch (comm_poll(loop_delay)) {
661#else
9ca89c5a 662 switch (comm_select(loop_delay)) {
812ed90c 663#endif
090089c4 664 case COMM_OK:
234967c9 665 errcount = 0; /* reset if successful */
090089c4 666 break;
667 case COMM_ERROR:
668 errcount++;
a3d5953d 669 debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
090089c4 670 if (errcount == 10)
4d64d74a 671 fatal_dump("Select Loop failed!");
090089c4 672 break;
4d64d74a 673 case COMM_SHUTDOWN:
43030d00 674 /* delayed close so we can transmit while shutdown pending */
30a4f2a8 675 if (theOutIcpConnection > 0) {
676 comm_close(theOutIcpConnection);
677 theOutIcpConnection = -1;
43030d00 678 }
5f3f8d0e 679 if (shutdown_pending) {
680 normal_shutdown();
dbe4fd8e 681 } else if (reconfigure_pending) {
682 mainReconfigure();
683 reconfigure_pending = 0; /* reset */
5f3f8d0e 684 } else {
685 fatal_dump("MAIN: SHUTDOWN from comm_select, but nothing pending.");
686 }
0ffd22bc 687 break;
9ca89c5a 688 case COMM_TIMEOUT:
6c93e119 689 break;
090089c4 690 default:
6eb42cae 691 fatal_dump("MAIN: Internal error -- this should never happen.");
090089c4 692 break;
693 }
694 }
695 /* NOTREACHED */
983061ed 696 return 0;
090089c4 697}
7690e8eb 698
b8d8561b 699static void
0673c0ba 700sendSignal(void)
7690e8eb 701{
ff8d0ea6 702 pid_t pid;
fedac7e5 703 debug_log = stderr;
704 if (ConfigFile == NULL)
705 ConfigFile = xstrdup(DefaultConfigFile);
1b635117 706 cbdataInit();
fedac7e5 707 parseConfigFile(ConfigFile);
708 pid = readPidFile();
709 if (pid > 1) {
710 if (kill(pid, opt_send_signal) &&
711 /* ignore permissions if just running check */
712 !(opt_send_signal == 0 && errno == EPERM)) {
713 fprintf(stderr, "%s: ERROR: Could not send ", appname);
714 fprintf(stderr, "signal %d to process %d: %s\n",
41d30aa8 715 opt_send_signal, (int) pid, xstrerror());
7690e8eb 716 exit(1);
717 }
fedac7e5 718 } else {
719 fprintf(stderr, "%s: ERROR: No running copy\n", appname);
720 exit(1);
7690e8eb 721 }
fedac7e5 722 /* signal successfully sent */
723 exit(0);
724}
f95b8144 725
726static void
bbe199dc 727watch_child(char *argv[])
f95b8144 728{
729 char *prog;
f95b8144 730 int failcount = 0;
731 time_t start;
732 time_t stop;
733#ifdef _SQUID_NEXT_
734 union wait status;
735#else
736 int status;
737#endif
738 if (*(argv[0]) == '(')
739 return;
740 for (;;) {
741 if (fork() == 0) {
742 /* child */
743 prog = xstrdup(argv[0]);
bbe199dc 744 argv[0] = xstrdup("(squid)");
745 execvp(prog, argv);
746 fatal("execvp failed");
f95b8144 747 }
748 /* parent */
749 time(&start);
750#ifdef _SQUID_NEXT_
751 wait3(&status, 0, NULL);
752#else
753 waitpid(-1, &status, 0);
754#endif
755 time(&stop);
756 if (stop - start < 10)
757 failcount++;
a8e69881 758 else
759 failcount = 0;
f95b8144 760 if (failcount == 5)
761 exit(1);
f95b8144 762 if (WIFEXITED(status))
763 if (WEXITSTATUS(status) == 0)
764 exit(0);
765 sleep(3);
766 }
bbe199dc 767 /* NOTREACHED */
f95b8144 768}