main.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:20k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: main.c,v 1.290 1999/01/24 04:03:52 wessels Exp $
  3.  *
  4.  * DEBUG: section 1     Startup and Main Loop
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.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 the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. /* for error reporting from xmalloc and friends */
  36. extern void (*failure_notify) (const char *);
  37. static int opt_send_signal = -1;
  38. static int opt_no_daemon = 0;
  39. static int opt_parse_cfg_only = 0;
  40. static int httpPortNumOverride = 1;
  41. static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
  42. static int configured_once = 0;
  43. #if MALLOC_DBG
  44. static int malloc_debug_level = 0;
  45. #endif
  46. static volatile int do_reconfigure = 0;
  47. static volatile int do_rotate = 0;
  48. static volatile int do_shutdown = 0;
  49. static void mainRotate(void);
  50. static void mainReconfigure(void);
  51. static SIGHDLR rotate_logs;
  52. static SIGHDLR reconfigure;
  53. #if ALARM_UPDATES_TIME
  54. static SIGHDLR time_tick;
  55. #endif
  56. static void mainInitialize(void);
  57. static void usage(void);
  58. static void mainParseOptions(int, char **);
  59. static void sendSignal(void);
  60. static void serverConnectionsOpen(void);
  61. static void watch_child(char **);
  62. static void setEffectiveUser(void);
  63. #if MEM_GEN_TRACE
  64. extern void log_trace_done();
  65. extern void log_trace_init(char *);
  66. #endif
  67. static EVH SquidShutdown;
  68. static void
  69. usage(void)
  70. {
  71.     fprintf(stderr,
  72. "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]n"
  73. "       -a port   Specify HTTP port number (default: %d).n"
  74. "       -d level  Write debugging to stderr also.n"
  75. "       -f file   Use given config-file instead ofn"
  76. "                 %sn"
  77. "       -h        Print help message.n"
  78. "       -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parsen"
  79. "                 Parse configuration file, then send signal to n"
  80. "                 running copy (except -k parse) and exit.n"
  81. "       -s        Enable logging to syslog.n"
  82. "       -u port   Specify ICP port number (default: %d), disable with 0.n"
  83. "       -v        Print version.n"
  84. "       -z        Create swap directoriesn"
  85. "       -C        Do not catch fatal signals.n"
  86. "       -D        Disable initial DNS tests.n"
  87. "       -F        Foreground fast store rebuild.n"
  88. "       -N        No daemon mode.n"
  89. "       -R        Do not set REUSEADDR on port.n"
  90. "       -V        Virtual host httpd-accelerator.n"
  91. "       -X        Force full debugging.n"
  92. "       -Y        Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.n",
  93. appname, CACHE_HTTP_PORT, DefaultConfigFile, CACHE_ICP_PORT);
  94.     exit(1);
  95. }
  96. static void
  97. mainParseOptions(int argc, char *argv[])
  98. {
  99.     extern char *optarg;
  100.     int c;
  101.     while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
  102. switch (c) {
  103. case 'C':
  104.     opt_catch_signals = 0;
  105.     break;
  106. case 'D':
  107.     opt_dns_tests = 0;
  108.     break;
  109. case 'F':
  110.     opt_foreground_rebuild = 1;
  111.     break;
  112. case 'N':
  113.     opt_no_daemon = 1;
  114.     break;
  115. case 'R':
  116.     opt_reuseaddr = 0;
  117.     break;
  118. case 'S':
  119.     opt_store_doublecheck = 1;
  120.     break;
  121. case 'V':
  122.     vhost_mode = 1;
  123.     break;
  124. case 'X':
  125.     /* force full debugging */
  126.     sigusr2_handle(SIGUSR2);
  127.     break;
  128. case 'Y':
  129.     opt_reload_hit_only = 1;
  130.     break;
  131. case 'a':
  132.     httpPortNumOverride = atoi(optarg);
  133.     break;
  134. case 'd':
  135.     opt_debug_stderr = atoi(optarg);
  136.     break;
  137. case 'f':
  138.     xfree(ConfigFile);
  139.     ConfigFile = xstrdup(optarg);
  140.     break;
  141. case 'h':
  142.     usage();
  143.     break;
  144. case 'k':
  145.     if ((int) strlen(optarg) < 1)
  146. usage();
  147.     if (!strncmp(optarg, "reconfigure", strlen(optarg)))
  148. opt_send_signal = SIGHUP;
  149.     else if (!strncmp(optarg, "rotate", strlen(optarg)))
  150. #ifdef _SQUID_LINUX_THREADS_
  151. opt_send_signal = SIGQUIT;
  152. #else
  153. opt_send_signal = SIGUSR1;
  154. #endif
  155.     else if (!strncmp(optarg, "debug", strlen(optarg)))
  156. #ifdef _SQUID_LINUX_THREADS_
  157. opt_send_signal = SIGTRAP;
  158. #else
  159. opt_send_signal = SIGUSR2;
  160. #endif
  161.     else if (!strncmp(optarg, "shutdown", strlen(optarg)))
  162. opt_send_signal = SIGTERM;
  163.     else if (!strncmp(optarg, "interrupt", strlen(optarg)))
  164. opt_send_signal = SIGINT;
  165.     else if (!strncmp(optarg, "kill", strlen(optarg)))
  166. opt_send_signal = SIGKILL;
  167.     else if (!strncmp(optarg, "check", strlen(optarg)))
  168. opt_send_signal = 0; /* SIGNULL */
  169.     else if (!strncmp(optarg, "parse", strlen(optarg)))
  170. opt_parse_cfg_only = 1; /* parse cfg file only */
  171.     else
  172. usage();
  173.     break;
  174. case 'm':
  175.     if (optarg) {
  176. #if MALLOC_DBG
  177. malloc_debug_level = atoi(optarg);
  178. /* NOTREACHED */
  179. break;
  180. #else
  181. fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
  182. /* NOTREACHED */
  183. #endif
  184.     } else {
  185. #if XMALLOC_TRACE
  186. xmalloc_trace = !xmalloc_trace;
  187. #else
  188. fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
  189. #endif
  190.     }
  191. case 's':
  192.     opt_syslog_enable = 1;
  193.     break;
  194. case 'u':
  195.     icpPortNumOverride = atoi(optarg);
  196.     if (icpPortNumOverride < 0)
  197. icpPortNumOverride = 0;
  198.     break;
  199. case 'v':
  200.     printf("Squid Cache: Version %sn", version_string);
  201.     exit(0);
  202.     /* NOTREACHED */
  203. case 'z':
  204.     opt_create_swap_dirs = 1;
  205.     break;
  206. case '?':
  207. default:
  208.     usage();
  209.     break;
  210. }
  211.     }
  212. }
  213. /* ARGSUSED */
  214. static void
  215. rotate_logs(int sig)
  216. {
  217.     do_rotate = 1;
  218. #if !HAVE_SIGACTION
  219.     signal(sig, rotate_logs);
  220. #endif
  221. }
  222. #if ALARM_UPDATES_TIME
  223. static void
  224. time_tick(int sig)
  225. {
  226.     getCurrentTime();
  227.     alarm(1);
  228. #if !HAVE_SIGACTION
  229.     signal(sig, time_tick);
  230. #endif
  231. }
  232. #endif
  233. /* ARGSUSED */
  234. static void
  235. reconfigure(int sig)
  236. {
  237.     do_reconfigure = 1;
  238. #if !HAVE_SIGACTION
  239.     signal(sig, reconfigure);
  240. #endif
  241. }
  242. void
  243. shut_down(int sig)
  244. {
  245.     do_shutdown = sig == SIGINT ? -1 : 1;
  246. #ifdef KILL_PARENT_OPT
  247.     if (getppid() > 1) {
  248. debug(1, 1) ("Killing RunCache, pid %dn", getppid());
  249. kill(getppid(), sig);
  250.     }
  251. #endif
  252. #if SA_RESETHAND == 0
  253.     signal(SIGTERM, SIG_DFL);
  254.     signal(SIGINT, SIG_DFL);
  255. #endif
  256. }
  257. static void
  258. serverConnectionsOpen(void)
  259. {
  260.     clientHttpConnectionsOpen();
  261.     icpConnectionsOpen();
  262. #if USE_HTCP
  263.     htcpInit();
  264. #endif
  265. #ifdef SQUID_SNMP
  266.     snmpConnectionOpen();
  267. #endif
  268.     clientdbInit();
  269.     icmpOpen();
  270.     netdbInit();
  271.     asnInit();
  272.     peerSelectInit();
  273. #if USE_CARP
  274.     carpInit();
  275. #endif
  276. }
  277. void
  278. serverConnectionsClose(void)
  279. {
  280.     assert(shutting_down || reconfiguring);
  281.     clientHttpConnectionsClose();
  282.     icpConnectionShutdown();
  283. #if USE_HTCP
  284.     htcpSocketShutdown();
  285. #endif
  286.     icmpClose();
  287. #ifdef SQUID_SNMP
  288.     snmpConnectionShutdown();
  289. #endif
  290.     asnFreeMemory();
  291. }
  292. static void
  293. mainReconfigure(void)
  294. {
  295.     debug(1, 1) ("Restarting Squid Cache (version %s)...n", version_string);
  296.     reconfiguring = 1;
  297.     /* Already called serverConnectionsClose and ipcacheShutdownServers() */
  298.     serverConnectionsClose();
  299.     icpConnectionClose();
  300. #if USE_HTCP
  301.     htcpSocketClose();
  302. #endif
  303. #ifdef SQUID_SNMP
  304.     snmpConnectionClose();
  305. #endif
  306.     dnsShutdown();
  307.     redirectShutdown();
  308.     authenticateShutdown();
  309.     storeDirCloseSwapLogs();
  310.     errorClean();
  311.     parseConfigFile(ConfigFile);
  312.     _db_init(Config.Log.log, Config.debugOptions);
  313.     ipcache_restart(); /* clear stuck entries */
  314.     fqdncache_restart(); /* sigh, fqdncache too */
  315.     errorInitialize(); /* reload error pages */
  316.     dnsInit();
  317.     redirectInit();
  318.     authenticateInit();
  319.     serverConnectionsOpen();
  320.     if (theOutIcpConnection >= 0) {
  321. if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
  322.     neighbors_open(theOutIcpConnection);
  323. else
  324.     debug(1, 1) ("ICP port disabled in httpd_accelerator moden");
  325.     }
  326.     storeDirOpenSwapLogs();
  327.     writePidFile(); /* write PID file */
  328.     debug(1, 1) ("Ready to serve requests.n");
  329.     reconfiguring = 0;
  330. }
  331. static void
  332. mainRotate(void)
  333. {
  334.     icmpClose();
  335.     _db_rotate_log(); /* cache.log */
  336.     storeDirWriteCleanLogs(1);
  337.     storeLogRotate(); /* store.log */
  338.     accessLogRotate(); /* access.log */
  339.     useragentRotateLog(); /* useragent.log */
  340.     icmpOpen();
  341. }
  342. static void
  343. setEffectiveUser(void)
  344. {
  345.     leave_suid(); /* Run as non privilegied user */
  346. #ifdef _SQUID_OS2_
  347.     return;
  348. #endif
  349.     if (geteuid() == 0) {
  350. debug(0, 0) ("Squid is not safe to run as root!  If you mustn");
  351. debug(0, 0) ("start Squid as root, then you must configuren");
  352. debug(0, 0) ("it to run as a non-priveledged user with then");
  353. debug(0, 0) ("'cache_effective_user' option in the config file.n");
  354. fatal("Don't run Squid as root, set 'cache_effective_user'!");
  355.     }
  356. }
  357. static void
  358. mainInitialize(void)
  359. {
  360.     if (opt_catch_signals) {
  361. squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
  362. squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
  363.     }
  364.     squid_signal(SIGPIPE, SIG_IGN, SA_RESTART);
  365.     squid_signal(SIGCHLD, sig_child, SA_NODEFER | SA_RESTART);
  366.     setEffectiveUser();
  367.     assert(Config.Port.http);
  368.     if (httpPortNumOverride != 1)
  369. Config.Port.http->i = (u_short) httpPortNumOverride;
  370.     if (icpPortNumOverride != 1)
  371. Config.Port.icp = (u_short) icpPortNumOverride;
  372.     _db_init(Config.Log.log, Config.debugOptions);
  373.     fd_open(fileno(debug_log), FD_LOG, Config.Log.log);
  374. #if MEM_GEN_TRACE
  375.     log_trace_init("/tmp/squid.alloc");
  376. #endif
  377.     debug(1, 0) ("Starting Squid Cache version %s for %s...n",
  378. version_string,
  379. CONFIG_HOST_TYPE);
  380.     debug(1, 1) ("Process ID %dn", (int) getpid());
  381.     debug(1, 1) ("With %d file descriptors availablen", Squid_MaxFD);
  382.     if (!configured_once)
  383. disk_init(); /* disk_init must go before ipcache_init() */
  384.     ipcache_init();
  385.     fqdncache_init();
  386.     dnsInit();
  387.     redirectInit();
  388.     authenticateInit();
  389.     useragentOpenLog();
  390.     httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
  391.     httpReplyInitModule(); /* must go before accepting replies */
  392.     errorInitialize();
  393.     accessLogInit();
  394. #if USE_IDENT
  395.     identInit();
  396. #endif
  397. #ifdef SQUID_SNMP
  398.     snmpInit();
  399. #endif
  400. #if MALLOC_DBG
  401.     malloc_debug(0, malloc_debug_level);
  402. #endif
  403.     if (!configured_once) {
  404. unlinkdInit();
  405. urlInitialize();
  406. cachemgrInit();
  407. statInit();
  408. storeInit();
  409. if (Config.effectiveUser) {
  410.     /* we were probably started as root, so cd to a swap
  411.      * directory in case we dump core */
  412.     if (chdir(storeSwapDir(0)) < 0) {
  413. debug(50, 0) ("%s: %sn", storeSwapDir(0), xstrerror());
  414. fatal_dump("Cannot cd to swap directory?");
  415.     }
  416. }
  417. /* after this point we want to see the mallinfo() output */
  418. do_mallinfo = 1;
  419. mimeInit(Config.mimeTablePathname);
  420. pconnInit();
  421. eventInit();
  422. refreshInit();
  423. #if DELAY_POOLS
  424. delayPoolsInit();
  425. #endif
  426. fwdInit();
  427.     }
  428.     serverConnectionsOpen();
  429.     if (theOutIcpConnection >= 0) {
  430. if (!Config2.Accel.on || Config.onoff.accel_with_proxy)
  431.     neighbors_open(theOutIcpConnection);
  432. else
  433.     debug(1, 1) ("ICP port disabled in httpd_accelerator moden");
  434.     }
  435.     if (!configured_once)
  436. writePidFile(); /* write PID file */
  437. #ifdef _SQUID_LINUX_THREADS_
  438.     squid_signal(SIGQUIT, rotate_logs, SA_RESTART);
  439.     squid_signal(SIGTRAP, sigusr2_handle, SA_RESTART);
  440. #else
  441.     squid_signal(SIGUSR1, rotate_logs, SA_RESTART);
  442.     squid_signal(SIGUSR2, sigusr2_handle, SA_RESTART);
  443. #endif
  444.     squid_signal(SIGHUP, reconfigure, SA_RESTART);
  445.     squid_signal(SIGTERM, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
  446.     squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
  447. #if ALARM_UPDATES_TIME
  448.     squid_signal(SIGALRM, time_tick, SA_RESTART);
  449.     alarm(1);
  450. #endif
  451.     debug(1, 1) ("Ready to serve requests.n");
  452.     if (!configured_once) {
  453. eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
  454. eventAdd("storeDirClean", storeDirClean, NULL, 15.0, 1);
  455. if (Config.onoff.announce)
  456.     eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
  457. eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1);
  458. eventAdd("fqdncache_purgelru", fqdncache_purgelru, NULL, 15.0, 1);
  459.     }
  460.     configured_once = 1;
  461. }
  462. int
  463. main(int argc, char **argv)
  464. {
  465.     int errcount = 0;
  466.     int n; /* # of GC'd objects */
  467.     time_t loop_delay;
  468.     debug_log = stderr;
  469.     if (FD_SETSIZE < Squid_MaxFD)
  470. Squid_MaxFD = FD_SETSIZE;
  471.     /* call mallopt() before anything else */
  472. #if HAVE_MALLOPT
  473. #ifdef M_GRAIN
  474.     /* Round up all sizes to a multiple of this */
  475.     mallopt(M_GRAIN, 16);
  476. #endif
  477. #ifdef M_MXFAST
  478.     /* biggest size that is considered a small block */
  479.     mallopt(M_MXFAST, 256);
  480. #endif
  481. #ifdef M_NBLKS
  482.     /* allocate this many small blocks at once */
  483.     mallopt(M_NLBLKS, 32);
  484. #endif
  485. #endif /* HAVE_MALLOPT */
  486.     memset(&local_addr, '', sizeof(struct in_addr));
  487.     safe_inet_addr(localhost, &local_addr);
  488.     memset(&any_addr, '', sizeof(struct in_addr));
  489.     safe_inet_addr("0.0.0.0", &any_addr);
  490.     memset(&no_addr, '', sizeof(struct in_addr));
  491.     safe_inet_addr("255.255.255.255", &no_addr);
  492.     squid_srandom(time(NULL));
  493.     getCurrentTime();
  494.     squid_start = current_time;
  495.     failure_notify = fatal_dump;
  496.     mainParseOptions(argc, argv);
  497.     /* parse configuration file
  498.      * note: in "normal" case this used to be called from mainInitialize() */
  499.     {
  500. int parse_err;
  501. if (!ConfigFile)
  502.     ConfigFile = xstrdup(DefaultConfigFile);
  503. assert(!configured_once);
  504. cbdataInit();
  505. #if USE_LEAKFINDER
  506. leakInit();
  507. #endif
  508. memInit(); /* memInit is required for config parsing */
  509. parse_err = parseConfigFile(ConfigFile);
  510. if (opt_parse_cfg_only)
  511.     return parse_err;
  512.     }
  513.     /* send signal to running copy and exit */
  514.     if (opt_send_signal != -1) {
  515. sendSignal();
  516. /* NOTREACHED */
  517.     }
  518.     if (opt_create_swap_dirs) {
  519. setEffectiveUser();
  520. debug(0, 0) ("Creating Swap Directoriesn");
  521. storeCreateSwapDirectories();
  522. return 0;
  523.     }
  524.     if (!opt_no_daemon)
  525. watch_child(argv);
  526.     setMaxFD();
  527.     if (opt_catch_signals)
  528. for (n = Squid_MaxFD; n > 2; n--)
  529.     close(n);
  530.     /* init comm module */
  531.     comm_init();
  532.     comm_select_init();
  533.     if (opt_no_daemon) {
  534. /* we have to init fdstat here. */
  535. fd_open(0, FD_LOG, "stdin");
  536. fd_open(1, FD_LOG, "stdout");
  537. fd_open(2, FD_LOG, "stderr");
  538.     }
  539.     mainInitialize();
  540.     /* main loop */
  541.     for (;;) {
  542. if (do_reconfigure) {
  543.     mainReconfigure();
  544.     do_reconfigure = 0;
  545. } else if (do_rotate) {
  546.     mainRotate();
  547.     do_rotate = 0;
  548. } else if (do_shutdown) {
  549.     time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
  550.     debug(1, 1) ("Preparing for shutdown after %d requestsn",
  551. Counter.client_http.requests);
  552.     debug(1, 1) ("Waiting %d seconds for active connections to finishn",
  553. wait);
  554.     do_shutdown = 0;
  555.     shutting_down = 1;
  556.     serverConnectionsClose();
  557.     dnsShutdown();
  558.     redirectShutdown();
  559.     authenticateShutdown();
  560.     eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
  561. }
  562. eventRun();
  563. if ((loop_delay = eventNextTime()) < 0)
  564.     loop_delay = 0;
  565. #if HAVE_POLL
  566. switch (comm_poll(loop_delay)) {
  567. #else
  568. switch (comm_select(loop_delay)) {
  569. #endif
  570. case COMM_OK:
  571.     errcount = 0; /* reset if successful */
  572.     break;
  573. case COMM_ERROR:
  574.     errcount++;
  575.     debug(1, 0) ("Select loop Error. Retry %dn", errcount);
  576.     if (errcount == 10)
  577. fatal_dump("Select Loop failed!");
  578.     break;
  579. case COMM_TIMEOUT:
  580.     break;
  581. case COMM_SHUTDOWN:
  582.     SquidShutdown(NULL);
  583.     break;
  584. default:
  585.     fatal_dump("MAIN: Internal error -- this should never happen.");
  586.     break;
  587. }
  588.     }
  589.     /* NOTREACHED */
  590.     return 0;
  591. }
  592. static void
  593. sendSignal(void)
  594. {
  595.     pid_t pid;
  596.     debug_log = stderr;
  597.     pid = readPidFile();
  598.     if (pid > 1) {
  599. if (kill(pid, opt_send_signal) &&
  600. /* ignore permissions if just running check */
  601.     !(opt_send_signal == 0 && errno == EPERM)) {
  602.     fprintf(stderr, "%s: ERROR: Could not send ", appname);
  603.     fprintf(stderr, "signal %d to process %d: %sn",
  604. opt_send_signal, (int) pid, xstrerror());
  605.     exit(1);
  606. }
  607.     } else {
  608. fprintf(stderr, "%s: ERROR: No running copyn", appname);
  609. exit(1);
  610.     }
  611.     /* signal successfully sent */
  612.     exit(0);
  613. }
  614. static void
  615. watch_child(char *argv[])
  616. {
  617.     char *prog;
  618.     int failcount = 0;
  619.     time_t start;
  620.     time_t stop;
  621. #ifdef _SQUID_NEXT_
  622.     union wait status;
  623. #else
  624.     int status;
  625. #endif
  626.     pid_t pid;
  627.     int i;
  628.     if (*(argv[0]) == '(')
  629. return;
  630.     openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
  631.     if ((pid = fork()) < 0)
  632. syslog(LOG_ALERT, "fork failed: %s", xstrerror());
  633.     else if (pid > 0)
  634. exit(0);
  635.     if (setsid() < 0)
  636. syslog(LOG_ALERT, "setsid failed: %s", xstrerror());
  637. #ifdef TIOCNOTTY
  638.     if ((i = open("/dev/tty", O_RDWR)) >= 0) {
  639. ioctl(i, TIOCNOTTY, NULL);
  640. close(i);
  641.     }
  642. #endif
  643.     for (i = 0; i < Squid_MaxFD; i++)
  644. close(i);
  645.     umask(0);
  646.     for (;;) {
  647. if ((pid = fork()) == 0) {
  648.     /* child */
  649.     prog = xstrdup(argv[0]);
  650.     argv[0] = xstrdup("(squid)");
  651.     execvp(prog, argv);
  652.     syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
  653. }
  654. /* parent */
  655. syslog(LOG_NOTICE, "Squid Parent: child process %d started", pid);
  656. time(&start);
  657. squid_signal(SIGINT, SIG_IGN, SA_RESTART);
  658. #ifdef _SQUID_NEXT_
  659. pid = wait3(&status, 0, NULL);
  660. #else
  661. pid = waitpid(-1, &status, 0);
  662. #endif
  663. time(&stop);
  664. if (WIFEXITED(status)) {
  665.     syslog(LOG_NOTICE,
  666. "Squid Parent: child process %d exited with status %d",
  667. pid, WEXITSTATUS(status));
  668. } else if (WIFSIGNALED(status)) {
  669.     syslog(LOG_NOTICE,
  670. "Squid Parent: child process %d exited due to signal %d",
  671. pid, WTERMSIG(status));
  672. } else {
  673.     syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
  674. }
  675. if (stop - start < 10)
  676.     failcount++;
  677. else
  678.     failcount = 0;
  679. if (failcount == 5) {
  680.     syslog(LOG_ALERT, "Exiting due to repeated, frequent failures");
  681.     exit(1);
  682. }
  683. if (WIFEXITED(status))
  684.     if (WEXITSTATUS(status) == 0)
  685. exit(0);
  686. squid_signal(SIGINT, SIG_DFL, SA_RESTART);
  687. sleep(3);
  688.     }
  689.     /* NOTREACHED */
  690. }
  691. static void
  692. SquidShutdown(void *unused)
  693. {
  694.     debug(1, 1) ("Shutting down...n");
  695.     if (Config.pidFilename && strcmp(Config.pidFilename, "none")) {
  696. enter_suid();
  697. safeunlink(Config.pidFilename, 0);
  698. leave_suid();
  699.     }
  700.     icpConnectionClose();
  701. #if USE_HTCP
  702.     htcpSocketClose();
  703. #endif
  704. #ifdef SQUID_SNMP
  705.     snmpConnectionClose();
  706. #endif
  707.     releaseServerSockets();
  708.     commCloseAllSockets();
  709.     unlinkdClose();
  710. #if USE_ASYNC_IO
  711.     aioSync(); /* flush pending object writes / unlinks */
  712. #endif
  713.     storeDirWriteCleanLogs(0);
  714.     PrintRusage();
  715.     dumpMallocStats();
  716. #if USE_ASYNC_IO
  717.     aioSync(); /* flush log writes */
  718. #endif
  719.     storeLogClose();
  720.     accessLogClose();
  721. #if USE_ASYNC_IO
  722.     aioSync(); /* flush log close */
  723. #endif
  724. #if PURIFY || XMALLOC_TRACE
  725.     configFreeMemory();
  726.     storeFreeMemory();
  727.     /*stmemFreeMemory(); */
  728.     netdbFreeMemory();
  729.     ipcacheFreeMemory();
  730.     fqdncacheFreeMemory();
  731.     asnFreeMemory();
  732.     clientdbFreeMemory();
  733.     httpHeaderCleanModule();
  734.     statFreeMemory();
  735.     eventFreeMemory();
  736.     mimeFreeMemory();
  737.     errorClean();
  738. #endif
  739. #if !XMALLOC_TRACE
  740.     if (opt_no_daemon) {
  741. file_close(0);
  742. file_close(1);
  743. file_close(2);
  744.     }
  745. #endif
  746.     fdDumpOpen();
  747.     fdFreeMemory();
  748.     memClean();
  749. #if XMALLOC_TRACE
  750.     xmalloc_find_leaks();
  751.     debug(1, 0) ("Memory used after shutdown: %dn", xmalloc_total);
  752. #endif
  753. #if MEM_GEN_TRACE
  754.     log_trace_done();
  755. #endif
  756.     debug(1, 1) ("Squid Cache (Version %s): Exiting normally.n",
  757. version_string);
  758.     fclose(debug_log);
  759.     exit(0);
  760. }