]> git.ipfire.org Git - thirdparty/squid.git/blame - src/main.cc
update
[thirdparty/squid.git] / src / main.cc
CommitLineData
30a4f2a8 1/*
d2af9477 2 * $Id: main.cc,v 1.49 1996/07/11 17:42:44 wessels Exp $
30a4f2a8 3 *
4 * DEBUG: section 1 Startup and Main Loop
5 * AUTHOR: Harvest Derived
6 *
7 * SQUID Internet Object Cache http://www.nlanr.net/Squid/
8 * --------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from the
11 * Internet community. Development is led by Duane Wessels of the
12 * National Laboratory for Applied Network Research and funded by
13 * the National Science Foundation.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 */
30
31/*
32 * Copyright (c) 1994, 1995. All rights reserved.
33 *
34 * The Harvest software was developed by the Internet Research Task
35 * Force Research Group on Resource Discovery (IRTF-RD):
36 *
37 * Mic Bowman of Transarc Corporation.
38 * Peter Danzig of the University of Southern California.
39 * Darren R. Hardy of the University of Colorado at Boulder.
40 * Udi Manber of the University of Arizona.
41 * Michael F. Schwartz of the University of Colorado at Boulder.
42 * Duane Wessels of the University of Colorado at Boulder.
43 *
44 * This copyright notice applies to software in the Harvest
45 * ``src/'' directory only. Users should consult the individual
46 * copyright notices in the ``components/'' subdirectories for
47 * copyright information about other software bundled with the
48 * Harvest source code distribution.
49 *
50 * TERMS OF USE
51 *
52 * The Harvest software may be used and re-distributed without
53 * charge, provided that the software origin and research team are
54 * cited in any use of the system. Most commonly this is
55 * accomplished by including a link to the Harvest Home Page
56 * (http://harvest.cs.colorado.edu/) from the query page of any
57 * Broker you deploy, as well as in the query result pages. These
58 * links are generated automatically by the standard Broker
59 * software distribution.
60 *
61 * The Harvest software is provided ``as is'', without express or
62 * implied warranty, and with no support nor obligation to assist
63 * in its use, correction, modification or enhancement. We assume
64 * no liability with respect to the infringement of copyrights,
65 * trade secrets, or any patents, and are not responsible for
66 * consequential damages. Proper use of the Harvest software is
67 * entirely the responsibility of the user.
68 *
69 * DERIVATIVE WORKS
70 *
71 * Users may make derivative works from the Harvest software, subject
72 * to the following constraints:
73 *
74 * - You must include the above copyright notice and these
75 * accompanying paragraphs in all forms of derivative works,
76 * and any documentation and other materials related to such
77 * distribution and use acknowledge that the software was
78 * developed at the above institutions.
79 *
80 * - You must notify IRTF-RD regarding your distribution of
81 * the derivative work.
82 *
83 * - You must clearly notify users that your are distributing
84 * a modified version and not the original Harvest software.
85 *
86 * - Any derivative product is also subject to these copyright
87 * and use restrictions.
88 *
89 * Note that the Harvest software is NOT in the public domain. We
90 * retain copyright, as specified above.
91 *
92 * HISTORY OF FREE SOFTWARE STATUS
93 *
94 * Originally we required sites to license the software in cases
95 * where they were going to build commercial products/services
96 * around Harvest. In June 1995 we changed this policy. We now
97 * allow people to use the core Harvest software (the code found in
98 * the Harvest ``src/'' directory) for free. We made this change
99 * in the interest of encouraging the widest possible deployment of
100 * the technology. The Harvest software is really a reference
101 * implementation of a set of protocols and formats, some of which
102 * we intend to standardize. We encourage commercial
103 * re-implementations of code complying to this set of standards.
104 */
44a47c6e 105
106#include "squid.h"
107
b8de7ebe 108time_t squid_starttime = 0;
44a47c6e 109time_t next_cleaning = 0;
30a4f2a8 110int theHttpConnection = -1;
111int theInIcpConnection = -1;
112int theOutIcpConnection = -1;
090089c4 113int do_reuse = 1;
d68adf86 114int opt_unlink_on_reload = 0;
30a4f2a8 115int opt_reload_hit_only = 0; /* only UDP_HIT during store relaod */
090089c4 116int catch_signals = 1;
30a4f2a8 117int opt_dns_tests = 1;
118int opt_foreground_rebuild = 0;
090089c4 119int vhost_mode = 0;
16128bc7 120int unbuffered_logs = 1; /* debug and hierarhcy unbuffered by default */
5f3f8d0e 121int shutdown_pending = 0; /* set by SIGTERM handler (shut_down()) */
122int reread_pending = 0; /* set by SIGHUP handler */
30a4f2a8 123char version_string[] = SQUID_VERSION;
124char appname[] = "squid";
125char localhost[] = "127.0.0.1";
126struct in_addr local_addr;
127
128/* for error reporting from xmalloc and friends */
129extern void (*failure_notify) _PARAMS((char *));
130
131static int rotate_pending = 0; /* set by SIGUSR1 handler */
132static int httpPortNumOverride = 1;
133static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
134#if MALLOC_DBG
4d64d74a 135static int malloc_debug_level = 0;
30a4f2a8 136#endif
137static void rotate_logs _PARAMS((int));
138static void reconfigure _PARAMS((int));
ccff9601 139
140static void usage()
141{
77ffc99f 142 fprintf(stderr, "\
30a4f2a8 143Usage: %s [-hsvzCDFRUVY] [-f config-file] [-[au] port]\n\
144 -a port Specify ASCII port number (default: %d).\n\
145 -f file Use given config-file instead of\n\
146 %s\n\
ccff9601 147 -h Print help message.\n\
148 -s Enable logging to syslog.\n\
30a4f2a8 149 -u port Specify UDP port number (default: %d), disable with 0.\n\
ccff9601 150 -v Print version.\n\
151 -z Zap disk storage -- deletes all objects in disk cache.\n\
152 -C Do not catch fatal signals.\n\
153 -D Disable initial DNS tests.\n\
30a4f2a8 154 -F Foreground fast store rebuild.\n\
ccff9601 155 -R Do not set REUSEADDR on port.\n\
d68adf86 156 -U Unlink expired objects on reload.\n\
30a4f2a8 157 -V Virtual host httpd-accelerator.\n\
158 -Y Only return UDP_HIT or UDP_DENIED during fast store reload.\n",
159 appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
77ffc99f 160 exit(1);
ccff9601 161}
162
4d64d74a 163static void mainParseOptions(argc, argv)
090089c4 164 int argc;
4d64d74a 165 char *argv[];
090089c4 166{
090089c4 167 extern char *optarg;
4d64d74a 168 int c;
090089c4 169
30a4f2a8 170 while ((c = getopt(argc, argv, "CDFRUVYa:bf:hm:su:vz?")) != -1) {
090089c4 171 switch (c) {
090089c4 172 case 'C':
173 catch_signals = 0;
174 break;
175 case 'D':
30a4f2a8 176 opt_dns_tests = 0;
090089c4 177 break;
30a4f2a8 178 case 'F':
179 opt_foreground_rebuild = 1;
090089c4 180 break;
090089c4 181 case 'R':
182 do_reuse = 0;
183 break;
d68adf86 184 case 'U':
185 opt_unlink_on_reload = 1;
186 break;
30a4f2a8 187 case 'V':
188 vhost_mode = 1;
189 break;
190 case 'Y':
191 opt_reload_hit_only = 1;
192 break;
193 case 'a':
194 httpPortNumOverride = atoi(optarg);
195 break;
196 case 'b':
197 unbuffered_logs = 0;
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;
090089c4 206 case 'm':
30a4f2a8 207#if MALLOC_DBG
090089c4 208 malloc_debug_level = atoi(optarg);
209 break;
30a4f2a8 210#else
211 fatal("Need to add -DMALLOC_DBG when compiling to use -m option");
212#endif
213 case 's':
214 syslog_enable = 0;
215 break;
216 case 'u':
217 icpPortNumOverride = atoi(optarg);
218 if (icpPortNumOverride < 0)
219 icpPortNumOverride = 0;
220 break;
221 case 'v':
222 printf("Squid Cache: Version %s\n", version_string);
223 exit(0);
224 /* NOTREACHED */
090089c4 225 case 'z':
226 zap_disk_store = 1;
227 break;
228 case '?':
090089c4 229 default:
ccff9601 230 usage();
090089c4 231 break;
232 }
090089c4 233 }
4d64d74a 234}
090089c4 235
30a4f2a8 236void rotate_logs(sig)
237 int sig;
238{
239 debug(21, 1, "rotate_logs: SIGUSR1 received.\n");
240 rotate_pending = 1;
241#if !HAVE_SIGACTION
242 signal(sig, rotate_logs);
243#endif
244}
245
246void reconfigure(sig)
247 int sig;
248{
249 debug(21, 1, "reconfigure: SIGHUP received\n");
250 debug(21, 1, "Waiting %d seconds for active connections to finish\n",
251 getShutdownLifetime());
252 reread_pending = 1;
253#if !HAVE_SIGACTION
254 signal(sig, reconfigure);
255#endif
256}
257
258void shut_down(sig)
259 int sig;
260{
261 debug(21, 1, "Preparing for shutdown after %d connections\n",
262 ntcpconn + nudpconn);
263 debug(21, 1, "Waiting %d seconds for active connections to finish\n",
264 getShutdownLifetime());
265 shutdown_pending = 1;
266}
267
5f3f8d0e 268void serverConnectionsOpen()
4d64d74a 269{
30a4f2a8 270 struct in_addr addr;
271 u_short port;
234967c9 272 /* Get our real priviliges */
234967c9 273
274 /* Open server ports */
30a4f2a8 275 enter_suid();
276 theHttpConnection = comm_open(COMM_NONBLOCKING,
277 getTcpIncomingAddr(),
278 getHttpPortNum(),
279 "HTTP Port");
280 leave_suid();
281 if (theHttpConnection < 0) {
282 fatal("Cannot open HTTP Port");
090089c4 283 }
30a4f2a8 284 fd_note(theHttpConnection, "HTTP socket");
285 comm_listen(theHttpConnection);
286 comm_set_select_handler(theHttpConnection,
090089c4 287 COMM_SELECT_READ,
288 asciiHandleConn,
289 0);
30a4f2a8 290 debug(1, 1, "Accepting HTTP connections on FD %d.\n",
291 theHttpConnection);
090089c4 292
293 if (!httpd_accel_mode || getAccelWithProxy()) {
30a4f2a8 294 if ((port = getIcpPortNum()) > 0) {
295 theInIcpConnection = comm_open(COMM_NONBLOCKING | COMM_DGRAM,
296 getUdpIncomingAddr(),
297 port,
298 "ICP Port");
299 if (theInIcpConnection < 0)
300 fatal("Cannot open ICP Port");
301 fd_note(theInIcpConnection, "ICP socket");
302 comm_set_select_handler(theInIcpConnection,
090089c4 303 COMM_SELECT_READ,
304 icpHandleUdp,
305 0);
30a4f2a8 306 debug(1, 1, "Accepting ICP connections on FD %d.\n",
307 theInIcpConnection);
308
309 if ((addr = getUdpOutgoingAddr()).s_addr != INADDR_NONE) {
310 theOutIcpConnection = comm_open(COMM_NONBLOCKING | COMM_DGRAM,
311 addr,
312 port,
313 "ICP Port");
314 if (theOutIcpConnection < 0)
315 fatal("Cannot open Outgoing ICP Port");
316 comm_set_select_handler(theOutIcpConnection,
317 COMM_SELECT_READ,
318 icpHandleUdp,
319 0);
320 debug(1, 1, "Accepting ICP connections on FD %d.\n",
321 theOutIcpConnection);
322 fd_note(theOutIcpConnection, "Outgoing ICP socket");
323 fd_note(theInIcpConnection, "Incoming ICP socket");
324 } else {
325 theOutIcpConnection = theInIcpConnection;
326 }
090089c4 327 }
328 }
5f3f8d0e 329}
330
331void serverConnectionsClose()
332{
30a4f2a8 333 /* NOTE, this function will be called repeatedly while shutdown
334 * is pending */
335 if (theHttpConnection >= 0) {
336 debug(21, 1, "FD %d Closing HTTP connection\n",
337 theHttpConnection);
338 comm_close(theHttpConnection);
339 comm_set_select_handler(theHttpConnection,
5f3f8d0e 340 COMM_SELECT_READ,
341 NULL,
342 0);
30a4f2a8 343 theHttpConnection = -1;
090089c4 344 }
30a4f2a8 345 if (theInIcpConnection >= 0) {
346 /* NOTE, don't close outgoing ICP connection, we need to write to
347 * it during shutdown */
348 debug(21, 1, "FD %d Closing ICP connection\n",
349 theInIcpConnection);
350 if (theInIcpConnection != theOutIcpConnection)
351 comm_close(theInIcpConnection);
352 comm_set_select_handler(theInIcpConnection,
5f3f8d0e 353 COMM_SELECT_READ,
354 NULL,
355 0);
30a4f2a8 356 if (theInIcpConnection != theOutIcpConnection)
357 comm_set_select_handler(theOutIcpConnection,
358 COMM_SELECT_READ,
359 NULL,
360 0);
361 theInIcpConnection = -1;
5f3f8d0e 362 }
363}
364
0ffd22bc 365static void mainReinitialize()
5f3f8d0e 366{
ad6272a1 367 debug(1, 0, "Restarting Squid Cache (version %s)...\n", version_string);
0ffd22bc 368 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
5f3f8d0e 369 neighborsDestroy();
0ffd22bc 370
00fac1f8 371 parseConfigFile(ConfigFile);
30a4f2a8 372 _db_init(getCacheLogFile(), getDebugOptions());
0ffd22bc 373 neighbors_init();
374 ipcacheOpenServers();
d2af9477 375 redirectOpenServers();
0ffd22bc 376 serverConnectionsOpen();
234967c9 377 (void) ftpInitialize();
30a4f2a8 378 if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
379 neighbors_open(theOutIcpConnection);
0ffd22bc 380 debug(1, 0, "Ready to serve requests.\n");
5f3f8d0e 381}
382
383static void mainInitialize()
384{
385 static int first_time = 1;
44f99671 386 if (catch_signals) {
30a4f2a8 387 squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
388 squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
44f99671 389 }
30a4f2a8 390 squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
391 squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
898f5d1d 392#if USE_ASYNC_IO
393 squid_signal(SIGIO, aioSigHandler, SA_RESTART);
394#endif
44f99671 395
00fac1f8 396 if (ConfigFile == NULL)
397 ConfigFile = xstrdup(DefaultConfigFile);
398 parseConfigFile(ConfigFile);
5f3f8d0e 399
30a4f2a8 400 leave_suid(); /* Run as non privilegied user */
5f3f8d0e 401
30a4f2a8 402 if (httpPortNumOverride != 1)
403 setHttpPortNum((u_short) httpPortNumOverride);
404 if (icpPortNumOverride != 1)
405 setIcpPortNum((u_short) icpPortNumOverride);
406
407 _db_init(getCacheLogFile(), getDebugOptions());
408 fdstat_open(fileno(debug_log), FD_LOG);
5f3f8d0e 409 fd_note(fileno(debug_log), getCacheLogFile());
410
30a4f2a8 411 debug(1, 0, "Starting Squid Cache version %s for %s...\n",
412 version_string,
413 CONFIG_HOST_TYPE);
414 debug(1, 1, "With %d file descriptors available\n", FD_SETSIZE);
5f3f8d0e 415
850c4ead 416 if (first_time) {
234967c9 417 disk_init(); /* disk_init must go before ipcache_init() */
30a4f2a8 418 writePidFile(); /* write PID file */
850c4ead 419 }
5f3f8d0e 420 ipcache_init();
d2af9477 421 redirectOpenServers();
5f3f8d0e 422 neighbors_init();
234967c9 423 (void) ftpInitialize();
5f3f8d0e 424
30a4f2a8 425#if MALLOC_DBG
5f3f8d0e 426 malloc_debug(0, malloc_debug_level);
427#endif
428
a26bdc75 429 if (first_time) {
430 first_time = 0;
5f3f8d0e 431 /* module initialization */
7111c86a 432 urlInitialize();
5f3f8d0e 433 stat_init(&CacheInfo, getAccessLogFile());
434 storeInit();
435 stmemInit();
090089c4 436
234967c9 437 if (getEffectiveUser()) {
438 /* we were probably started as root, so cd to a swap
439 * directory in case we dump core */
440 if (chdir(swappath(0)) < 0) {
441 debug(1, 0, "%s: %s\n", swappath(0), xstrerror());
442 fatal_dump("Cannot cd to swap directory?");
443 }
444 }
5f3f8d0e 445 /* after this point we want to see the mallinfo() output */
446 do_mallinfo = 1;
447 }
2285407f 448 serverConnectionsOpen();
30a4f2a8 449 if (theOutIcpConnection >= 0 && (!httpd_accel_mode || getAccelWithProxy()))
450 neighbors_open(theOutIcpConnection);
451
452 squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
453 squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
454 squid_signal(SIGHUP, reconfigure, SA_RESTART);
455 squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
456 squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
5f3f8d0e 457 debug(1, 0, "Ready to serve requests.\n");
4d64d74a 458}
459
460
461int main(argc, argv)
462 int argc;
463 char **argv;
464{
465 int errcount = 0;
4d64d74a 466 int n; /* # of GC'd objects */
467 time_t last_maintain = 0;
7d49daab 468 time_t last_announce = 0;
bc528c78 469 time_t loop_delay;
4d64d74a 470
30a4f2a8 471 memset(&local_addr, '\0', sizeof(struct in_addr));
472 local_addr.s_addr = inet_addr(localhost);
473
4d64d74a 474 errorInitialize();
475
b8de7ebe 476 squid_starttime = getCurrentTime();
4d64d74a 477 failure_notify = fatal_dump;
478
479 mainParseOptions(argc, argv);
480
481 setMaxFD();
482
30a4f2a8 483 if (catch_signals)
484 for (n = FD_SETSIZE; n > 2; n--)
485 close(n);
4d64d74a 486
487#if HAVE_MALLOPT
30a4f2a8 488#ifdef M_GRAIN
489 /* Round up all sizes to a multiple of this */
4d64d74a 490 mallopt(M_GRAIN, 16);
30a4f2a8 491#endif
492#ifdef M_MXFAST
4d64d74a 493 /* biggest size that is considered a small block */
30a4f2a8 494 mallopt(M_MXFAST, 256);
4d64d74a 495#endif
30a4f2a8 496#ifdef M_NBLKS
497 /* allocate this many small blocks at once */
498 mallopt(M_NLBLKS, 32);
499#endif
500#endif /* HAVE_MALLOPT */
4d64d74a 501
502 /*init comm module */
503 comm_init();
504
505 /* we have to init fdstat here. */
506 fdstat_init(PREOPEN_FD);
30a4f2a8 507 fdstat_open(0, FD_LOG);
508 fdstat_open(1, FD_LOG);
509 fdstat_open(2, FD_LOG);
4d64d74a 510 fd_note(0, "STDIN");
511 fd_note(1, "STDOUT");
512 fd_note(2, "STDERR");
513
4d64d74a 514 /* enable syslog by default */
515 syslog_enable = 0;
516
517 /* preinit for debug module */
518 debug_log = stderr;
519 hash_init(0);
520
4d64d74a 521 mainInitialize();
522
090089c4 523 /* main loop */
524 if (getCleanRate() > 0)
931b5039 525 next_cleaning = time(NULL) + getCleanRate();
983061ed 526 for (;;) {
30a4f2a8 527 loop_delay = (time_t) 10;
090089c4 528 /* maintain cache storage */
b8de7ebe 529 if (squid_curtime > last_maintain) {
090089c4 530 storeMaintainSwapSpace();
b8de7ebe 531 last_maintain = squid_curtime;
090089c4 532 }
30a4f2a8 533 if (rotate_pending) {
534 ftpServerClose();
535 _db_rotate_log(); /* cache.log */
536 storeWriteCleanLog();
537 storeRotateLog(); /* store.log */
538 neighbors_rotate_log(); /* hierarchy.log */
539 stat_rotate_log(); /* access.log */
540 (void) ftpInitialize();
541 rotate_pending = 0;
542 }
bc528c78 543 /* do background processing */
544 if (doBackgroundProcessing())
545 loop_delay = (time_t) 0;
546 switch (comm_select(loop_delay, next_cleaning)) {
090089c4 547 case COMM_OK:
234967c9 548 errcount = 0; /* reset if successful */
090089c4 549 break;
550 case COMM_ERROR:
551 errcount++;
234967c9 552 debug(1, 0, "Select loop Error. Retry %d\n", errcount);
090089c4 553 if (errcount == 10)
4d64d74a 554 fatal_dump("Select Loop failed!");
090089c4 555 break;
556 case COMM_TIMEOUT:
b8de7ebe 557 if (getCleanRate() > 0 && squid_curtime >= next_cleaning) {
019dd986 558 debug(1, 1, "Performing a garbage collection...\n");
090089c4 559 n = storePurgeOld();
019dd986 560 debug(1, 1, "Garbage collection done, %d objects removed\n", n);
b8de7ebe 561 next_cleaning = squid_curtime + getCleanRate();
090089c4 562 }
7d49daab 563 if ((n = getAnnounceRate()) > 0) {
b8de7ebe 564 if (squid_curtime > last_announce + n)
7ba794f4 565 send_announce();
b8de7ebe 566 last_announce = squid_curtime;
7d49daab 567 }
090089c4 568 /* house keeping */
090089c4 569 break;
4d64d74a 570 case COMM_SHUTDOWN:
43030d00 571 /* delayed close so we can transmit while shutdown pending */
30a4f2a8 572 if (theOutIcpConnection > 0) {
573 comm_close(theOutIcpConnection);
574 theOutIcpConnection = -1;
43030d00 575 }
5f3f8d0e 576 if (shutdown_pending) {
577 normal_shutdown();
578 exit(0);
579 } else if (reread_pending) {
0ffd22bc 580 mainReinitialize();
5f3f8d0e 581 reread_pending = 0; /* reset */
582 } else {
583 fatal_dump("MAIN: SHUTDOWN from comm_select, but nothing pending.");
584 }
0ffd22bc 585 break;
090089c4 586 default:
6eb42cae 587 fatal_dump("MAIN: Internal error -- this should never happen.");
090089c4 588 break;
589 }
590 }
591 /* NOTREACHED */
592 exit(0);
983061ed 593 return 0;
090089c4 594}