]>
Commit | Line | Data |
---|---|---|
a47b9029 | 1 | |
30a4f2a8 | 2 | /* |
9bc73deb | 3 | * $Id: main.cc,v 1.305 1999/10/04 05:05:17 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/ |
e25c139f | 9 | * ---------------------------------------------------------- |
30a4f2a8 | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * 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" | |
37 | ||
30a4f2a8 | 38 | /* for error reporting from xmalloc and friends */ |
ea3a2a69 | 39 | extern void (*failure_notify) (const char *); |
30a4f2a8 | 40 | |
f1dc9b30 | 41 | static int opt_send_signal = -1; |
f95b8144 | 42 | static int opt_no_daemon = 0; |
e13ee7ad | 43 | static int opt_parse_cfg_only = 0; |
30a4f2a8 | 44 | static int httpPortNumOverride = 1; |
45 | static int icpPortNumOverride = 1; /* Want to detect "-u 0" */ | |
e13ee7ad | 46 | static int configured_once = 0; |
30a4f2a8 | 47 | #if MALLOC_DBG |
4d64d74a | 48 | static int malloc_debug_level = 0; |
30a4f2a8 | 49 | #endif |
5cd39a10 | 50 | static volatile int do_reconfigure = 0; |
51 | static volatile int do_rotate = 0; | |
2681d383 | 52 | static volatile int do_shutdown = 0; |
4d7add01 | 53 | |
5cd39a10 | 54 | static void mainRotate(void); |
55 | static void mainReconfigure(void); | |
b984c445 | 56 | static SIGHDLR rotate_logs; |
57 | static SIGHDLR reconfigure; | |
58 | #if ALARM_UPDATES_TIME | |
59 | static SIGHDLR time_tick; | |
60 | #endif | |
f5b8bbc4 | 61 | static void mainInitialize(void); |
f5b8bbc4 | 62 | static void usage(void); |
63 | static void mainParseOptions(int, char **); | |
64 | static void sendSignal(void); | |
65 | static void serverConnectionsOpen(void); | |
bbe199dc | 66 | static void watch_child(char **); |
85407535 | 67 | static void setEffectiveUser(void); |
36a97e19 | 68 | #if MEM_GEN_TRACE |
69 | extern void log_trace_done(); | |
70 | extern void log_trace_init(char *); | |
71 | #endif | |
d723bf6b | 72 | static EVH SquidShutdown; |
b6a2f15e | 73 | static void mainSetCwd(void); |
85407535 | 74 | |
9bc73deb | 75 | #if TEST_ACCESS |
76 | #include "test_access.c" | |
77 | #endif | |
78 | ||
b8d8561b | 79 | static void |
0673c0ba | 80 | usage(void) |
ccff9601 | 81 | { |
0ee4272b | 82 | fprintf(stderr, |
969c39b9 | 83 | "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n" |
15df8349 | 84 | " -a port Specify HTTP port number (default: %d).\n" |
b6157f5e | 85 | " -d level Write debugging to stderr also.\n" |
0ee4272b | 86 | " -f file Use given config-file instead of\n" |
87 | " %s\n" | |
88 | " -h Print help message.\n" | |
e13ee7ad | 89 | " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n" |
90 | " Parse configuration file, then send signal to \n" | |
91 | " running copy (except -k parse) and exit.\n" | |
0ee4272b | 92 | " -s Enable logging to syslog.\n" |
93 | " -u port Specify ICP port number (default: %d), disable with 0.\n" | |
94 | " -v Print version.\n" | |
85407535 | 95 | " -z Create swap directories\n" |
0ee4272b | 96 | " -C Do not catch fatal signals.\n" |
97 | " -D Disable initial DNS tests.\n" | |
a411c763 | 98 | " -F Don't serve any requests until store is rebuilt.\n" |
969c39b9 | 99 | " -N No daemon mode.\n" |
0ee4272b | 100 | " -R Do not set REUSEADDR on port.\n" |
0ee4272b | 101 | " -V Virtual host httpd-accelerator.\n" |
3013ac6d | 102 | " -X Force full debugging.\n" |
429fdbec | 103 | " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n", |
30a4f2a8 | 104 | appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT); |
77ffc99f | 105 | exit(1); |
ccff9601 | 106 | } |
107 | ||
b8d8561b | 108 | static void |
109 | mainParseOptions(int argc, char *argv[]) | |
090089c4 | 110 | { |
090089c4 | 111 | extern char *optarg; |
4d64d74a | 112 | int c; |
090089c4 | 113 | |
723e8aa3 | 114 | while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) { |
090089c4 | 115 | switch (c) { |
090089c4 | 116 | case 'C': |
1758c627 | 117 | opt_catch_signals = 0; |
090089c4 | 118 | break; |
119 | case 'D': | |
30a4f2a8 | 120 | opt_dns_tests = 0; |
090089c4 | 121 | break; |
30a4f2a8 | 122 | case 'F': |
123 | opt_foreground_rebuild = 1; | |
090089c4 | 124 | break; |
f95b8144 | 125 | case 'N': |
126 | opt_no_daemon = 1; | |
9e2225aa | 127 | break; |
090089c4 | 128 | case 'R': |
3b4be6a6 | 129 | opt_reuseaddr = 0; |
090089c4 | 130 | break; |
b109de6b | 131 | case 'S': |
132 | opt_store_doublecheck = 1; | |
133 | break; | |
30a4f2a8 | 134 | case 'V': |
135 | vhost_mode = 1; | |
136 | break; | |
e924600d | 137 | case 'X': |
138 | /* force full debugging */ | |
139 | sigusr2_handle(SIGUSR2); | |
140 | break; | |
30a4f2a8 | 141 | case 'Y': |
142 | opt_reload_hit_only = 1; | |
143 | break; | |
144 | case 'a': | |
145 | httpPortNumOverride = atoi(optarg); | |
146 | break; | |
0d90407c | 147 | case 'd': |
723e8aa3 | 148 | opt_debug_stderr = atoi(optarg); |
0d90407c | 149 | break; |
090089c4 | 150 | case 'f': |
00fac1f8 | 151 | xfree(ConfigFile); |
152 | ConfigFile = xstrdup(optarg); | |
090089c4 | 153 | break; |
30a4f2a8 | 154 | case 'h': |
155 | usage(); | |
090089c4 | 156 | break; |
7690e8eb | 157 | case 'k': |
24382924 | 158 | if ((int) strlen(optarg) < 1) |
7690e8eb | 159 | usage(); |
160 | if (!strncmp(optarg, "reconfigure", strlen(optarg))) | |
161 | opt_send_signal = SIGHUP; | |
162 | else if (!strncmp(optarg, "rotate", strlen(optarg))) | |
7e7a0442 | 163 | #ifdef _SQUID_LINUX_THREADS_ |
e3175d1f | 164 | opt_send_signal = SIGQUIT; |
165 | #else | |
7690e8eb | 166 | opt_send_signal = SIGUSR1; |
e3175d1f | 167 | #endif |
7690e8eb | 168 | else if (!strncmp(optarg, "debug", strlen(optarg))) |
7e7a0442 | 169 | #ifdef _SQUID_LINUX_THREADS_ |
e3175d1f | 170 | opt_send_signal = SIGTRAP; |
171 | #else | |
7690e8eb | 172 | opt_send_signal = SIGUSR2; |
e3175d1f | 173 | #endif |
7690e8eb | 174 | else if (!strncmp(optarg, "shutdown", strlen(optarg))) |
175 | opt_send_signal = SIGTERM; | |
6759a5fb | 176 | else if (!strncmp(optarg, "interrupt", strlen(optarg))) |
177 | opt_send_signal = SIGINT; | |
7690e8eb | 178 | else if (!strncmp(optarg, "kill", strlen(optarg))) |
179 | opt_send_signal = SIGKILL; | |
180 | else if (!strncmp(optarg, "check", strlen(optarg))) | |
fedac7e5 | 181 | opt_send_signal = 0; /* SIGNULL */ |
e13ee7ad | 182 | else if (!strncmp(optarg, "parse", strlen(optarg))) |
8a6218c6 | 183 | opt_parse_cfg_only = 1; /* parse cfg file only */ |
7690e8eb | 184 | else |
185 | usage(); | |
186 | break; | |
090089c4 | 187 | case 'm': |
33ab18e8 | 188 | if (optarg) { |
30a4f2a8 | 189 | #if MALLOC_DBG |
33ab18e8 | 190 | malloc_debug_level = atoi(optarg); |
191 | /* NOTREACHED */ | |
192 | break; | |
30a4f2a8 | 193 | #else |
33ab18e8 | 194 | fatal("Need to add -DMALLOC_DBG when compiling to use -mX option"); |
195 | /* NOTREACHED */ | |
196 | #endif | |
197 | } else { | |
198 | #if XMALLOC_TRACE | |
199 | xmalloc_trace = !xmalloc_trace; | |
200 | #else | |
201 | fatal("Need to configure --enable-xmalloc-debug-trace to use -m option"); | |
30a4f2a8 | 202 | #endif |
33ab18e8 | 203 | } |
30a4f2a8 | 204 | case 's': |
6e40f263 | 205 | opt_syslog_enable = 1; |
30a4f2a8 | 206 | break; |
207 | case 'u': | |
208 | icpPortNumOverride = atoi(optarg); | |
209 | if (icpPortNumOverride < 0) | |
210 | icpPortNumOverride = 0; | |
211 | break; | |
212 | case 'v': | |
213 | printf("Squid Cache: Version %s\n", version_string); | |
214 | exit(0); | |
215 | /* NOTREACHED */ | |
090089c4 | 216 | case 'z': |
85407535 | 217 | opt_create_swap_dirs = 1; |
090089c4 | 218 | break; |
219 | case '?': | |
090089c4 | 220 | default: |
ccff9601 | 221 | usage(); |
090089c4 | 222 | break; |
223 | } | |
090089c4 | 224 | } |
4d64d74a | 225 | } |
090089c4 | 226 | |
7a2f978b | 227 | /* ARGSUSED */ |
b8d8561b | 228 | static void |
229 | rotate_logs(int sig) | |
30a4f2a8 | 230 | { |
5cd39a10 | 231 | do_rotate = 1; |
30a4f2a8 | 232 | #if !HAVE_SIGACTION |
233 | signal(sig, rotate_logs); | |
234 | #endif | |
235 | } | |
236 | ||
b984c445 | 237 | #if ALARM_UPDATES_TIME |
97c03d3c | 238 | static void |
239 | time_tick(int sig) | |
240 | { | |
241 | getCurrentTime(); | |
242 | alarm(1); | |
243 | #if !HAVE_SIGACTION | |
244 | signal(sig, time_tick); | |
245 | #endif | |
246 | } | |
38d04788 | 247 | |
b984c445 | 248 | #endif |
97c03d3c | 249 | |
7a2f978b | 250 | /* ARGSUSED */ |
b8d8561b | 251 | static void |
252 | reconfigure(int sig) | |
30a4f2a8 | 253 | { |
5cd39a10 | 254 | do_reconfigure = 1; |
30a4f2a8 | 255 | #if !HAVE_SIGACTION |
256 | signal(sig, reconfigure); | |
257 | #endif | |
258 | } | |
259 | ||
b8d8561b | 260 | void |
261 | shut_down(int sig) | |
30a4f2a8 | 262 | { |
2681d383 | 263 | do_shutdown = sig == SIGINT ? -1 : 1; |
cadc2d55 | 264 | #ifdef KILL_PARENT_OPT |
5cd39a10 | 265 | if (getppid() > 1) { |
266 | debug(1, 1) ("Killing RunCache, pid %d\n", getppid()); | |
267 | kill(getppid(), sig); | |
88738790 | 268 | } |
cadc2d55 | 269 | #endif |
6e40f263 | 270 | #if SA_RESETHAND == 0 |
271 | signal(SIGTERM, SIG_DFL); | |
272 | signal(SIGINT, SIG_DFL); | |
273 | #endif | |
30a4f2a8 | 274 | } |
275 | ||
24382924 | 276 | static void |
0673c0ba | 277 | serverConnectionsOpen(void) |
4d64d74a | 278 | { |
15df8349 | 279 | clientHttpConnectionsOpen(); |
280 | icpConnectionsOpen(); | |
ace287ee | 281 | #if USE_HTCP |
282 | htcpInit(); | |
283 | #endif | |
678c6099 | 284 | #ifdef SQUID_SNMP |
3265e68d | 285 | snmpConnectionOpen(); |
320e9f36 | 286 | #endif |
eb824054 | 287 | #if USE_WCCP |
320e9f36 | 288 | wccpConnectionOpen(); |
2bbd722b | 289 | #endif |
5ecceaa4 | 290 | clientdbInit(); |
16b204c4 | 291 | icmpOpen(); |
67508012 | 292 | netdbInit(); |
f899fac1 | 293 | asnInit(); |
85034133 | 294 | peerSelectInit(); |
afd88fbe | 295 | #if USE_CARP |
296 | carpInit(); | |
297 | #endif | |
5f3f8d0e | 298 | } |
299 | ||
b8d8561b | 300 | void |
0673c0ba | 301 | serverConnectionsClose(void) |
5f3f8d0e | 302 | { |
0a5a8601 | 303 | assert(shutting_down || reconfiguring); |
c0fbae16 | 304 | clientHttpConnectionsClose(); |
17e6c0a1 | 305 | icpConnectionShutdown(); |
72549e05 | 306 | #if USE_HTCP |
307 | htcpSocketShutdown(); | |
308 | #endif | |
c0fbae16 | 309 | icmpClose(); |
15df8349 | 310 | #ifdef SQUID_SNMP |
17e6c0a1 | 311 | snmpConnectionShutdown(); |
320e9f36 | 312 | #endif |
eb824054 | 313 | #if USE_WCCP |
320e9f36 | 314 | wccpConnectionShutdown(); |
15df8349 | 315 | #endif |
4bac8de8 | 316 | asnFreeMemory(); |
5f3f8d0e | 317 | } |
318 | ||
b8d8561b | 319 | static void |
dbe4fd8e | 320 | mainReconfigure(void) |
5f3f8d0e | 321 | { |
a60f7062 | 322 | debug(1, 1) ("Restarting Squid Cache (version %s)...\n", version_string); |
5cd39a10 | 323 | reconfiguring = 1; |
0ffd22bc | 324 | /* Already called serverConnectionsClose and ipcacheShutdownServers() */ |
15df8349 | 325 | serverConnectionsClose(); |
17e6c0a1 | 326 | icpConnectionClose(); |
72549e05 | 327 | #if USE_HTCP |
328 | htcpSocketClose(); | |
329 | #endif | |
17e6c0a1 | 330 | #ifdef SQUID_SNMP |
331 | snmpConnectionClose(); | |
320e9f36 | 332 | #endif |
eb824054 | 333 | #if USE_WCCP |
320e9f36 | 334 | wccpConnectionClose(); |
17e6c0a1 | 335 | #endif |
74addf6c | 336 | dnsShutdown(); |
eb824054 | 337 | #if !USE_DNSSERVERS |
7b724b86 | 338 | idnsShutdown(); |
eb824054 | 339 | #endif |
74addf6c | 340 | redirectShutdown(); |
341 | authenticateShutdown(); | |
2db68ce5 | 342 | storeDirCloseSwapLogs(); |
c68e9c6b | 343 | errorClean(); |
9c021a38 | 344 | mimeFreeMemory(); |
00fac1f8 | 345 | parseConfigFile(ConfigFile); |
b6f794d6 | 346 | _db_init(Config.Log.log, Config.debugOptions); |
429fdbec | 347 | ipcache_restart(); /* clear stuck entries */ |
348 | fqdncache_restart(); /* sigh, fqdncache too */ | |
53ad48e6 | 349 | errorInitialize(); /* reload error pages */ |
74addf6c | 350 | dnsInit(); |
eb824054 | 351 | #if !USE_DNSSERVERS |
7b724b86 | 352 | idnsInit(); |
eb824054 | 353 | #endif |
74addf6c | 354 | redirectInit(); |
355 | authenticateInit(); | |
1f38f50a | 356 | #if USE_WCCP |
357 | wccpInit(); | |
358 | #endif | |
0ffd22bc | 359 | serverConnectionsOpen(); |
e06ce23a | 360 | if (theOutIcpConnection >= 0) { |
5942e8d4 | 361 | if (!Config2.Accel.on || Config.onoff.accel_with_proxy) |
e06ce23a | 362 | neighbors_open(theOutIcpConnection); |
363 | else | |
364 | debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n"); | |
365 | } | |
2db68ce5 | 366 | storeDirOpenSwapLogs(); |
9c021a38 | 367 | mimeInit(Config.mimeTablePathname); |
b8890359 | 368 | writePidFile(); /* write PID file */ |
aebbcd07 | 369 | debug(1, 1) ("Ready to serve requests.\n"); |
5cd39a10 | 370 | reconfiguring = 0; |
371 | } | |
372 | ||
373 | static void | |
374 | mainRotate(void) | |
375 | { | |
376 | icmpClose(); | |
377 | _db_rotate_log(); /* cache.log */ | |
378 | storeDirWriteCleanLogs(1); | |
379 | storeLogRotate(); /* store.log */ | |
380 | accessLogRotate(); /* access.log */ | |
381 | useragentRotateLog(); /* useragent.log */ | |
382 | icmpOpen(); | |
5f3f8d0e | 383 | } |
384 | ||
067bea91 | 385 | static void |
85407535 | 386 | setEffectiveUser(void) |
387 | { | |
388 | leave_suid(); /* Run as non privilegied user */ | |
cd377065 | 389 | #ifdef _SQUID_OS2_ |
390 | return; | |
391 | #endif | |
85407535 | 392 | if (geteuid() == 0) { |
393 | debug(0, 0) ("Squid is not safe to run as root! If you must\n"); | |
394 | debug(0, 0) ("start Squid as root, then you must configure\n"); | |
395 | debug(0, 0) ("it to run as a non-priveledged user with the\n"); | |
396 | debug(0, 0) ("'cache_effective_user' option in the config file.\n"); | |
397 | fatal("Don't run Squid as root, set 'cache_effective_user'!"); | |
398 | } | |
399 | } | |
400 | ||
b6a2f15e | 401 | static void |
402 | mainSetCwd(void) | |
403 | { | |
404 | if (Config.coredump_dir) { | |
405 | if (!chdir(Config.coredump_dir)) { | |
406 | debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir); | |
407 | return; | |
408 | } else { | |
409 | debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror()); | |
410 | } | |
411 | } | |
412 | if (!Config.effectiveUser) { | |
413 | char *p = getcwd(NULL, 0); | |
414 | debug(0, 1) ("Current Directory is %s\n", p); | |
415 | xfree(p); | |
416 | return; | |
417 | } | |
418 | /* we were probably started as root, so cd to a swap | |
419 | * directory in case we dump core */ | |
420 | if (!chdir(storeSwapDir(0))) { | |
421 | debug(0, 1) ("Set Current Directory to %s\n", storeSwapDir(0)); | |
422 | return; | |
423 | } else { | |
424 | debug(50, 0) ("%s: %s\n", storeSwapDir(0), xstrerror()); | |
425 | fatal_dump("Cannot cd to swap directory?"); | |
426 | } | |
427 | } | |
428 | ||
b8d8561b | 429 | static void |
0673c0ba | 430 | mainInitialize(void) |
5f3f8d0e | 431 | { |
1758c627 | 432 | if (opt_catch_signals) { |
30a4f2a8 | 433 | squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND); |
434 | squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND); | |
44f99671 | 435 | } |
30a4f2a8 | 436 | squid_signal(SIGPIPE, SIG_IGN, SA_RESTART); |
437 | squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART); | |
44f99671 | 438 | |
85407535 | 439 | setEffectiveUser(); |
270b86af | 440 | assert(Config.Port.http); |
30a4f2a8 | 441 | if (httpPortNumOverride != 1) |
270b86af | 442 | Config.Port.http->i = (u_short) httpPortNumOverride; |
30a4f2a8 | 443 | if (icpPortNumOverride != 1) |
f2052513 | 444 | Config.Port.icp = (u_short) icpPortNumOverride; |
30a4f2a8 | 445 | |
b6f794d6 | 446 | _db_init(Config.Log.log, Config.debugOptions); |
5c5783a2 | 447 | fd_open(fileno(debug_log), FD_LOG, Config.Log.log); |
71a17702 | 448 | #if MEM_GEN_TRACE |
449 | log_trace_init("/tmp/squid.alloc"); | |
450 | #endif | |
a3d5953d | 451 | debug(1, 0) ("Starting Squid Cache version %s for %s...\n", |
30a4f2a8 | 452 | version_string, |
453 | CONFIG_HOST_TYPE); | |
aebbcd07 | 454 | debug(1, 1) ("Process ID %d\n", (int) getpid()); |
a3d5953d | 455 | debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD); |
5f3f8d0e | 456 | |
9f75c559 | 457 | if (!configured_once) |
234967c9 | 458 | disk_init(); /* disk_init must go before ipcache_init() */ |
5f3f8d0e | 459 | ipcache_init(); |
f88bb09c | 460 | fqdncache_init(); |
74addf6c | 461 | dnsInit(); |
eb824054 | 462 | #if !USE_DNSSERVERS |
7b724b86 | 463 | idnsInit(); |
eb824054 | 464 | #endif |
74addf6c | 465 | redirectInit(); |
466 | authenticateInit(); | |
b012353a | 467 | useragentOpenLog(); |
2ac76861 | 468 | httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ |
2246b732 | 469 | httpReplyInitModule(); /* must go before accepting replies */ |
9b312a19 | 470 | errorInitialize(); |
7a2f978b | 471 | accessLogInit(); |
3898f57f | 472 | #if USE_IDENT |
05832ae1 | 473 | identInit(); |
3898f57f | 474 | #endif |
5e14bf6d | 475 | #ifdef SQUID_SNMP |
476 | snmpInit(); | |
477 | #endif | |
30a4f2a8 | 478 | #if MALLOC_DBG |
5f3f8d0e | 479 | malloc_debug(0, malloc_debug_level); |
480 | #endif | |
481 | ||
dbe4fd8e | 482 | if (!configured_once) { |
1f38f50a | 483 | #if USE_ASYNC_IO |
484 | aioInit(); | |
485 | #endif | |
429fdbec | 486 | unlinkdInit(); |
7111c86a | 487 | urlInitialize(); |
22f3fd98 | 488 | cachemgrInit(); |
a7c05555 | 489 | statInit(); |
5f3f8d0e | 490 | storeInit(); |
b6a2f15e | 491 | mainSetCwd(); |
5f3f8d0e | 492 | /* after this point we want to see the mallinfo() output */ |
493 | do_mallinfo = 1; | |
812ed90c | 494 | mimeInit(Config.mimeTablePathname); |
603a02fd | 495 | pconnInit(); |
1c3e77cd | 496 | refreshInit(); |
0d7e5d78 | 497 | #if DELAY_POOLS |
95e36d02 | 498 | delayPoolsInit(); |
0d7e5d78 | 499 | #endif |
8ddcc35d | 500 | fwdInit(); |
5f3f8d0e | 501 | } |
1f38f50a | 502 | #if USE_WCCP |
503 | wccpInit(); | |
504 | #endif | |
2285407f | 505 | serverConnectionsOpen(); |
e06ce23a | 506 | if (theOutIcpConnection >= 0) { |
5942e8d4 | 507 | if (!Config2.Accel.on || Config.onoff.accel_with_proxy) |
e06ce23a | 508 | neighbors_open(theOutIcpConnection); |
509 | else | |
510 | debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n"); | |
511 | } | |
dbe4fd8e | 512 | if (!configured_once) |
0a5b9b32 | 513 | writePidFile(); /* write PID file */ |
514 | ||
7e7a0442 | 515 | #ifdef _SQUID_LINUX_THREADS_ |
e3175d1f | 516 | squid_signal(SIGQUIT, rotate_logs, SA_RESTART); |
517 | squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART); | |
518 | #else | |
30a4f2a8 | 519 | squid_signal(SIGUSR1, rotate_logs, SA_RESTART); |
520 | squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART); | |
9fc0b4b8 | 521 | #endif |
30a4f2a8 | 522 | squid_signal(SIGHUP, reconfigure, SA_RESTART); |
523 | squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART); | |
524 | squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART); | |
b984c445 | 525 | #if ALARM_UPDATES_TIME |
97c03d3c | 526 | squid_signal(SIGALRM, time_tick, SA_RESTART); |
527 | alarm(1); | |
b984c445 | 528 | #endif |
58a39dc9 | 529 | memCheckInit(); |
aebbcd07 | 530 | debug(1, 1) ("Ready to serve requests.\n"); |
dbe4fd8e | 531 | if (!configured_once) { |
52040193 | 532 | eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1); |
17a0a4ee | 533 | if (Config.onoff.announce) |
52040193 | 534 | eventAdd("start_announce", start_announce, NULL, 3600.0, 1); |
535 | eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1); | |
536 | eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1); | |
4d7add01 | 537 | } |
dbe4fd8e | 538 | configured_once = 1; |
4d64d74a | 539 | } |
540 | ||
b8d8561b | 541 | int |
542 | main(int argc, char **argv) | |
4d64d74a | 543 | { |
544 | int errcount = 0; | |
4d64d74a | 545 | int n; /* # of GC'd objects */ |
bc528c78 | 546 | time_t loop_delay; |
4d64d74a | 547 | |
88738790 | 548 | debug_log = stderr; |
e83892e9 | 549 | if (FD_SETSIZE < Squid_MaxFD) |
550 | Squid_MaxFD = FD_SETSIZE; | |
399e85ea | 551 | |
7328e889 | 552 | /* call mallopt() before anything else */ |
0b29fe44 | 553 | #if HAVE_MALLOPT |
7328e889 | 554 | #ifdef M_GRAIN |
555 | /* Round up all sizes to a multiple of this */ | |
556 | mallopt(M_GRAIN, 16); | |
557 | #endif | |
558 | #ifdef M_MXFAST | |
559 | /* biggest size that is considered a small block */ | |
560 | mallopt(M_MXFAST, 256); | |
561 | #endif | |
562 | #ifdef M_NBLKS | |
563 | /* allocate this many small blocks at once */ | |
564 | mallopt(M_NLBLKS, 32); | |
565 | #endif | |
566 | #endif /* HAVE_MALLOPT */ | |
567 | ||
30a4f2a8 | 568 | memset(&local_addr, '\0', sizeof(struct in_addr)); |
429fdbec | 569 | safe_inet_addr(localhost, &local_addr); |
28070024 | 570 | memset(&any_addr, '\0', sizeof(struct in_addr)); |
429fdbec | 571 | safe_inet_addr("0.0.0.0", &any_addr); |
28070024 | 572 | memset(&no_addr, '\0', sizeof(struct in_addr)); |
429fdbec | 573 | safe_inet_addr("255.255.255.255", &no_addr); |
88738790 | 574 | squid_srandom(time(NULL)); |
4d64d74a | 575 | |
f2908497 | 576 | getCurrentTime(); |
577 | squid_start = current_time; | |
4d64d74a | 578 | failure_notify = fatal_dump; |
579 | ||
580 | mainParseOptions(argc, argv); | |
581 | ||
e13ee7ad | 582 | /* parse configuration file |
583 | * note: in "normal" case this used to be called from mainInitialize() */ | |
584 | { | |
585 | int parse_err; | |
586 | if (!ConfigFile) | |
587 | ConfigFile = xstrdup(DefaultConfigFile); | |
3cc5715b | 588 | assert(!configured_once); |
589 | cbdataInit(); | |
5d620373 | 590 | #if USE_LEAKFINDER |
591 | leakInit(); | |
592 | #endif | |
3cc5715b | 593 | memInit(); /* memInit is required for config parsing */ |
9bc73deb | 594 | eventInit(); /* eventInit() is required for config parsing */ |
e13ee7ad | 595 | parse_err = parseConfigFile(ConfigFile); |
8a6218c6 | 596 | |
e13ee7ad | 597 | if (opt_parse_cfg_only) |
598 | return parse_err; | |
599 | } | |
600 | ||
9bc73deb | 601 | #if TEST_ACCESS |
602 | comm_init(); | |
603 | comm_select_init(); | |
604 | mainInitialize(); | |
605 | test_access(); | |
606 | return 0; | |
607 | #endif | |
608 | ||
7690e8eb | 609 | /* send signal to running copy and exit */ |
610 | if (opt_send_signal != -1) { | |
611 | sendSignal(); | |
612 | /* NOTREACHED */ | |
613 | } | |
85407535 | 614 | if (opt_create_swap_dirs) { |
067bea91 | 615 | setEffectiveUser(); |
616 | debug(0, 0) ("Creating Swap Directories\n"); | |
617 | storeCreateSwapDirectories(); | |
618 | return 0; | |
619 | } | |
f95b8144 | 620 | if (!opt_no_daemon) |
bbe199dc | 621 | watch_child(argv); |
4d64d74a | 622 | setMaxFD(); |
623 | ||
1758c627 | 624 | if (opt_catch_signals) |
e83892e9 | 625 | for (n = Squid_MaxFD; n > 2; n--) |
30a4f2a8 | 626 | close(n); |
4d64d74a | 627 | |
e13ee7ad | 628 | /* init comm module */ |
4d64d74a | 629 | comm_init(); |
6a988308 | 630 | comm_select_init(); |
4d64d74a | 631 | |
54f742e7 | 632 | if (opt_no_daemon) { |
633 | /* we have to init fdstat here. */ | |
634 | fd_open(0, FD_LOG, "stdin"); | |
635 | fd_open(1, FD_LOG, "stdout"); | |
636 | fd_open(2, FD_LOG, "stderr"); | |
637 | } | |
4d64d74a | 638 | mainInitialize(); |
639 | ||
090089c4 | 640 | /* main loop */ |
983061ed | 641 | for (;;) { |
5cd39a10 | 642 | if (do_reconfigure) { |
969c39b9 | 643 | mainReconfigure(); |
5cd39a10 | 644 | do_reconfigure = 0; |
645 | } else if (do_rotate) { | |
646 | mainRotate(); | |
647 | do_rotate = 0; | |
2681d383 | 648 | } else if (do_shutdown) { |
73c9ccc5 | 649 | time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0; |
5cd39a10 | 650 | debug(1, 1) ("Preparing for shutdown after %d requests\n", |
651 | Counter.client_http.requests); | |
652 | debug(1, 1) ("Waiting %d seconds for active connections to finish\n", | |
73c9ccc5 | 653 | wait); |
2681d383 | 654 | do_shutdown = 0; |
655 | shutting_down = 1; | |
d723bf6b | 656 | serverConnectionsClose(); |
74addf6c | 657 | dnsShutdown(); |
eb824054 | 658 | #if !USE_DNSSERVERS |
7b724b86 | 659 | idnsShutdown(); |
eb824054 | 660 | #endif |
74addf6c | 661 | redirectShutdown(); |
662 | authenticateShutdown(); | |
d723bf6b | 663 | eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1); |
30a4f2a8 | 664 | } |
48f44632 | 665 | eventRun(); |
666 | if ((loop_delay = eventNextTime()) < 0) | |
4d7add01 | 667 | loop_delay = 0; |
812ed90c | 668 | #if HAVE_POLL |
669 | switch (comm_poll(loop_delay)) { | |
670 | #else | |
9ca89c5a | 671 | switch (comm_select(loop_delay)) { |
812ed90c | 672 | #endif |
090089c4 | 673 | case COMM_OK: |
234967c9 | 674 | errcount = 0; /* reset if successful */ |
090089c4 | 675 | break; |
676 | case COMM_ERROR: | |
677 | errcount++; | |
a3d5953d | 678 | debug(1, 0) ("Select loop Error. Retry %d\n", errcount); |
090089c4 | 679 | if (errcount == 10) |
4d64d74a | 680 | fatal_dump("Select Loop failed!"); |
090089c4 | 681 | break; |
9ca89c5a | 682 | case COMM_TIMEOUT: |
6c93e119 | 683 | break; |
d723bf6b | 684 | case COMM_SHUTDOWN: |
685 | SquidShutdown(NULL); | |
686 | break; | |
090089c4 | 687 | default: |
6eb42cae | 688 | fatal_dump("MAIN: Internal error -- this should never happen."); |
090089c4 | 689 | break; |
690 | } | |
691 | } | |
692 | /* NOTREACHED */ | |
983061ed | 693 | return 0; |
090089c4 | 694 | } |
7690e8eb | 695 | |
b8d8561b | 696 | static void |
0673c0ba | 697 | sendSignal(void) |
7690e8eb | 698 | { |
ff8d0ea6 | 699 | pid_t pid; |
fedac7e5 | 700 | debug_log = stderr; |
fedac7e5 | 701 | pid = readPidFile(); |
702 | if (pid > 1) { | |
703 | if (kill(pid, opt_send_signal) && | |
704 | /* ignore permissions if just running check */ | |
705 | !(opt_send_signal == 0 && errno == EPERM)) { | |
706 | fprintf(stderr, "%s: ERROR: Could not send ", appname); | |
707 | fprintf(stderr, "signal %d to process %d: %s\n", | |
41d30aa8 | 708 | opt_send_signal, (int) pid, xstrerror()); |
7690e8eb | 709 | exit(1); |
710 | } | |
fedac7e5 | 711 | } else { |
712 | fprintf(stderr, "%s: ERROR: No running copy\n", appname); | |
713 | exit(1); | |
7690e8eb | 714 | } |
fedac7e5 | 715 | /* signal successfully sent */ |
716 | exit(0); | |
717 | } | |
f95b8144 | 718 | |
719 | static void | |
bbe199dc | 720 | watch_child(char *argv[]) |
f95b8144 | 721 | { |
722 | char *prog; | |
f95b8144 | 723 | int failcount = 0; |
724 | time_t start; | |
725 | time_t stop; | |
726 | #ifdef _SQUID_NEXT_ | |
727 | union wait status; | |
728 | #else | |
729 | int status; | |
730 | #endif | |
e3a3b845 | 731 | pid_t pid; |
54f742e7 | 732 | int i; |
f95b8144 | 733 | if (*(argv[0]) == '(') |
734 | return; | |
54f742e7 | 735 | openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4); |
736 | if ((pid = fork()) < 0) | |
737 | syslog(LOG_ALERT, "fork failed: %s", xstrerror()); | |
738 | else if (pid > 0) | |
739 | exit(0); | |
740 | if (setsid() < 0) | |
741 | syslog(LOG_ALERT, "setsid failed: %s", xstrerror()); | |
742 | #ifdef TIOCNOTTY | |
743 | if ((i = open("/dev/tty", O_RDWR)) >= 0) { | |
744 | ioctl(i, TIOCNOTTY, NULL); | |
745 | close(i); | |
746 | } | |
747 | #endif | |
748 | for (i = 0; i < Squid_MaxFD; i++) | |
749 | close(i); | |
1ecaa0a0 | 750 | #if NOT_NEEDED |
54f742e7 | 751 | umask(0); |
1ecaa0a0 | 752 | #endif |
f95b8144 | 753 | for (;;) { |
54f742e7 | 754 | if ((pid = fork()) == 0) { |
f95b8144 | 755 | /* child */ |
756 | prog = xstrdup(argv[0]); | |
bbe199dc | 757 | argv[0] = xstrdup("(squid)"); |
758 | execvp(prog, argv); | |
54f742e7 | 759 | syslog(LOG_ALERT, "execvp failed: %s", xstrerror()); |
f95b8144 | 760 | } |
54f742e7 | 761 | /* parent */ |
762 | syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid); | |
763 | time(&start); | |
764 | squid_signal(SIGINT, SIG_IGN, SA_RESTART); | |
f95b8144 | 765 | #ifdef _SQUID_NEXT_ |
54f742e7 | 766 | pid = wait3(&status, 0, NULL); |
f95b8144 | 767 | #else |
54f742e7 | 768 | pid = waitpid(-1, &status, 0); |
f95b8144 | 769 | #endif |
770 | time(&stop); | |
54f742e7 | 771 | if (WIFEXITED(status)) { |
772 | syslog(LOG_NOTICE, | |
773 | "Squid Parent: child process %d exited with status %d", | |
774 | pid, WEXITSTATUS(status)); | |
775 | } else if (WIFSIGNALED(status)) { | |
776 | syslog(LOG_NOTICE, | |
777 | "Squid Parent: child process %d exited due to signal %d", | |
778 | pid, WTERMSIG(status)); | |
779 | } else { | |
780 | syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid); | |
781 | } | |
f95b8144 | 782 | if (stop - start < 10) |
783 | failcount++; | |
a8e69881 | 784 | else |
785 | failcount = 0; | |
54f742e7 | 786 | if (failcount == 5) { |
787 | syslog(LOG_ALERT, "Exiting due to repeated, frequent failures"); | |
f95b8144 | 788 | exit(1); |
54f742e7 | 789 | } |
f95b8144 | 790 | if (WIFEXITED(status)) |
791 | if (WEXITSTATUS(status) == 0) | |
792 | exit(0); | |
0fb4fc71 | 793 | squid_signal(SIGINT, SIG_DFL, SA_RESTART); |
f95b8144 | 794 | sleep(3); |
795 | } | |
bbe199dc | 796 | /* NOTREACHED */ |
f95b8144 | 797 | } |
fff6ad65 | 798 | |
9ec1a1dc | 799 | static void |
d723bf6b | 800 | SquidShutdown(void *unused) |
fff6ad65 | 801 | { |
802 | debug(1, 1) ("Shutting down...\n"); | |
803 | if (Config.pidFilename && strcmp(Config.pidFilename, "none")) { | |
804 | enter_suid(); | |
805 | safeunlink(Config.pidFilename, 0); | |
806 | leave_suid(); | |
807 | } | |
d723bf6b | 808 | icpConnectionClose(); |
809 | #if USE_HTCP | |
810 | htcpSocketClose(); | |
811 | #endif | |
812 | #ifdef SQUID_SNMP | |
813 | snmpConnectionClose(); | |
320e9f36 | 814 | #endif |
eb824054 | 815 | #if USE_WCCP |
320e9f36 | 816 | wccpConnectionClose(); |
d723bf6b | 817 | #endif |
fff6ad65 | 818 | releaseServerSockets(); |
d723bf6b | 819 | commCloseAllSockets(); |
fff6ad65 | 820 | unlinkdClose(); |
ddb43c58 | 821 | #if USE_ASYNC_IO |
822 | aioSync(); /* flush pending object writes / unlinks */ | |
823 | #endif | |
fff6ad65 | 824 | storeDirWriteCleanLogs(0); |
825 | PrintRusage(); | |
826 | dumpMallocStats(); | |
ddb43c58 | 827 | #if USE_ASYNC_IO |
828 | aioSync(); /* flush log writes */ | |
829 | #endif | |
fff6ad65 | 830 | storeLogClose(); |
831 | accessLogClose(); | |
ddb43c58 | 832 | #if USE_ASYNC_IO |
833 | aioSync(); /* flush log close */ | |
834 | #endif | |
33ab18e8 | 835 | #if PURIFY || XMALLOC_TRACE |
fff6ad65 | 836 | configFreeMemory(); |
837 | storeFreeMemory(); | |
33ab18e8 | 838 | /*stmemFreeMemory(); */ |
fff6ad65 | 839 | netdbFreeMemory(); |
840 | ipcacheFreeMemory(); | |
841 | fqdncacheFreeMemory(); | |
842 | asnFreeMemory(); | |
26a369ba | 843 | clientdbFreeMemory(); |
7021844c | 844 | httpHeaderCleanModule(); |
d2db411c | 845 | statFreeMemory(); |
f1fc2a8d | 846 | eventFreeMemory(); |
c68e9c6b | 847 | mimeFreeMemory(); |
848 | errorClean(); | |
fff6ad65 | 849 | #endif |
26a369ba | 850 | #if !XMALLOC_TRACE |
54f742e7 | 851 | if (opt_no_daemon) { |
852 | file_close(0); | |
853 | file_close(1); | |
854 | file_close(2); | |
855 | } | |
33ab18e8 | 856 | #endif |
fff6ad65 | 857 | fdDumpOpen(); |
858 | fdFreeMemory(); | |
ddb43c58 | 859 | memClean(); |
33ab18e8 | 860 | #if XMALLOC_TRACE |
26a369ba | 861 | xmalloc_find_leaks(); |
862 | debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total); | |
33ab18e8 | 863 | #endif |
36a97e19 | 864 | #if MEM_GEN_TRACE |
399e85ea | 865 | log_trace_done(); |
36a97e19 | 866 | #endif |
a60f7062 | 867 | debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n", |
fff6ad65 | 868 | version_string); |
869 | fclose(debug_log); | |
870 | exit(0); | |
871 | } |