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