3 * $Id: main.cc,v 1.391 2004/04/04 13:48:32 hno Exp $
5 * DEBUG: section 1 Startup and Main Loop
6 * AUTHOR: Harvest Derived
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
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.
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.
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
37 #include "AccessLogEntry.h"
38 #include "authenticate.h"
41 #include "HttpReply.h"
46 #include "StoreFileSystem.h"
51 #include "squid_windows.h"
54 static int opt_install_service
= FALSE
;
55 static int opt_remove_service
= FALSE
;
56 static int opt_signal_service
= FALSE
;
57 static int opt_command_line
= FALSE
;
58 extern void WIN32_svcstatusupdate(DWORD
, DWORD
);
59 void WINAPI
WIN32_svcHandler(DWORD
);
63 /* for error reporting from xmalloc and friends */
64 SQUIDCEXTERN
void (*failure_notify
) (const char *);
66 static int opt_send_signal
= -1;
67 static int opt_parse_cfg_only
= 0;
68 static int icpPortNumOverride
= 1; /* Want to detect "-u 0" */
69 static int configured_once
= 0;
71 static int malloc_debug_level
= 0;
73 static volatile int do_reconfigure
= 0;
74 static volatile int do_rotate
= 0;
75 static volatile int do_shutdown
= 0;
77 static void mainRotate(void);
78 static void mainReconfigure(void);
79 static void mainInitialize(void);
80 static void usage(void);
81 static void mainParseOptions(int, char **);
82 static void sendSignal(void);
83 static void serverConnectionsOpen(void);
84 static void watch_child(char **);
85 static void setEffectiveUser(void);
87 extern void log_trace_done();
88 extern void log_trace_init(char *);
90 static EVH SquidShutdown
;
91 static void mainSetCwd(void);
92 static int checkRunningPid(void);
95 static const char *squid_start_script
= "squid_start";
99 #include "test_access.c"
106 #if USE_WIN32_SERVICE
107 "Usage: %s [-dhirsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal] [-n name] [-O CommandLine]\n"
109 "Usage: %s [-dhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
111 " -a port Specify HTTP port number (default: %d).\n"
112 " -d level Write debugging to stderr also.\n"
113 " -f file Use given config-file instead of\n"
115 " -h Print help message.\n"
116 #if USE_WIN32_SERVICE
117 " -i Installs as a Windows Service (see -n option).\n"
119 " -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse\n"
120 " Parse configuration file, then send signal to \n"
121 " running copy (except -k parse) and exit.\n"
122 #if USE_WIN32_SERVICE
123 " -n name Specify Windows Service name to use for service operations\n"
124 " default is: " _WIN_SQUID_DEFAULT_SERVICE_NAME
".\n"
125 " -r Removes a Windows Service (see -n option).\n"
127 " -s Enable logging to syslog.\n"
128 " -u port Specify ICP port number (default: %d), disable with 0.\n"
129 " -v Print version.\n"
130 " -z Create swap directories\n"
131 " -C Do not catch fatal signals.\n"
132 " -D Disable initial DNS tests.\n"
133 " -F Don't serve any requests until store is rebuilt.\n"
134 " -N No daemon mode.\n"
135 #if USE_WIN32_SERVICE
137 " Set Windows Service Command line options in Registry.\n"
139 " -R Do not set REUSEADDR on port.\n"
140 " -S Double-check swap during rebuild.\n"
141 " -V Virtual host httpd-accelerator.\n"
142 " -X Force full debugging.\n"
143 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
144 appname
, CACHE_HTTP_PORT
, DefaultConfigFile
, CACHE_ICP_PORT
);
149 mainParseOptions(int argc
, char *argv
[])
154 #if USE_WIN32_SERVICE
156 while ((c
= getopt(argc
, argv
, "CDFNO:RSVYXa:d:f:hik:m::n:rsu:vz?")) != -1)
159 while ((c
= getopt(argc
, argv
, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1)
168 opt_catch_signals
= 0;
176 opt_foreground_rebuild
= 1;
182 #if USE_WIN32_SERVICE
185 opt_command_line
= 1;
186 WIN32_Command_Line
= xstrdup(optarg
);
195 opt_store_doublecheck
= 1;
200 if (Config
.Sockaddr
.http
)
201 Config
.Sockaddr
.http
->vhost
= 1;
205 else if (Config
.Sockaddr
.https
)
206 Config
.Sockaddr
.https
->http
.vhost
= 1;
211 fatal("No http_port specified\n");
216 /* force full debugging */
217 sigusr2_handle(SIGUSR2
);
222 opt_reload_hit_only
= 1;
226 #if USE_WIN32_SERVICE
229 opt_install_service
= TRUE
;
236 add_http_port(optarg
);
241 opt_debug_stderr
= atoi(optarg
);
248 ConfigFile
= xstrdup(optarg
);
258 if ((int) strlen(optarg
) < 1)
261 if (!strncmp(optarg
, "reconfigure", strlen(optarg
)))
262 opt_send_signal
= SIGHUP
;
263 else if (!strncmp(optarg
, "rotate", strlen(optarg
)))
264 #ifdef _SQUID_LINUX_THREADS_
266 opt_send_signal
= SIGQUIT
;
270 opt_send_signal
= SIGUSR1
;
274 else if (!strncmp(optarg
, "debug", strlen(optarg
)))
275 #ifdef _SQUID_LINUX_THREADS_
277 opt_send_signal
= SIGTRAP
;
281 opt_send_signal
= SIGUSR2
;
285 else if (!strncmp(optarg
, "shutdown", strlen(optarg
)))
286 opt_send_signal
= SIGTERM
;
287 else if (!strncmp(optarg
, "interrupt", strlen(optarg
)))
288 opt_send_signal
= SIGINT
;
289 else if (!strncmp(optarg
, "kill", strlen(optarg
)))
290 opt_send_signal
= SIGKILL
;
291 else if (!strncmp(optarg
, "check", strlen(optarg
)))
292 opt_send_signal
= 0; /* SIGNULL */
293 else if (!strncmp(optarg
, "parse", strlen(optarg
)))
294 opt_parse_cfg_only
= 1; /* parse cfg file only */
303 malloc_debug_level
= atoi(optarg
);
308 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
314 xmalloc_trace
= !xmalloc_trace
;
317 fatal("Need to configure --enable-xmalloc-debug-trace to use -m option");
322 #if USE_WIN32_SERVICE
325 xfree(WIN32_Service_name
);
327 WIN32_Service_name
= xstrdup(optarg
);
329 opt_signal_service
= TRUE
;
334 opt_remove_service
= TRUE
;
343 opt_syslog_enable
= 1;
349 fatal("Logging to syslog not available on this platform");
355 icpPortNumOverride
= atoi(optarg
);
357 if (icpPortNumOverride
< 0)
358 icpPortNumOverride
= 0;
363 printf("Squid Cache: Version %s\nconfigure options: %s\n", version_string
, SQUID_CONFIGURE_OPTIONS
);
365 #if USE_WIN32_SERVICE
367 printf("Compiled as Windows System Service.\n");
376 opt_create_swap_dirs
= 1;
396 #ifndef _SQUID_MSWIN_
399 signal(sig
, rotate_logs
);
409 #ifndef _SQUID_MSWIN_
412 signal(sig
, reconfigure
);
420 do_shutdown
= sig
== SIGINT
? -1 : 1;
421 #ifndef _SQUID_MSWIN_
422 #ifdef KILL_PARENT_OPT
425 debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
427 if (kill(getppid(), sig
) < 0)
428 debug(1, 1) ("kill %d: %s\n", getppid(), xstrerror());
432 #if SA_RESETHAND == 0
433 signal(SIGTERM
, SIG_DFL
);
435 signal(SIGINT
, SIG_DFL
);
442 serverConnectionsOpen(void)
444 clientOpenListenSockets();
445 icpConnectionsOpen();
452 snmpConnectionOpen();
456 wccpConnectionOpen();
472 serverConnectionsClose(void)
474 assert(shutting_down
|| reconfiguring
);
475 clientHttpConnectionsClose();
476 icpConnectionShutdown();
479 htcpSocketShutdown();
485 snmpConnectionShutdown();
489 wccpConnectionShutdown();
496 mainReconfigure(void)
498 debug(1, 1) ("Reconfiguring Squid Cache (version %s)...\n", version_string
);
500 /* Already called serverConnectionsClose and ipcacheShutdownServers() */
501 serverConnectionsClose();
502 icpConnectionClose();
509 snmpConnectionClose();
513 wccpConnectionClose();
524 authenticateShutdown();
525 externalAclShutdown();
526 storeDirCloseSwapLogs();
532 enter_suid(); /* root to read config file */
533 parseConfigFile(ConfigFile
);
535 _db_init(Config
.Log
.log
, Config
.debugOptions
);
536 ipcache_restart(); /* clear stuck entries */
537 authenticateUserCacheRestart(); /* clear stuck ACL entries */
538 fqdncache_restart(); /* sigh, fqdncache too */
540 errorInitialize(); /* reload error pages */
554 authenticateInit(&Config
.authConfiguration
);
561 serverConnectionsOpen();
563 storeDirOpenSwapLogs();
564 mimeInit(Config
.mimeTablePathname
);
565 writePidFile(); /* write PID file */
566 debug(1, 1) ("Ready to serve requests.\n");
580 authenticateShutdown();
581 externalAclShutdown();
582 _db_rotate_log(); /* cache.log */
583 storeDirWriteCleanLogs(1);
584 storeLogRotate(); /* store.log */
585 accessLogRotate(); /* access.log */
586 useragentRotateLog(); /* useragent.log */
587 refererRotateLog(); /* referer.log */
600 authenticateInit(&Config
.authConfiguration
);
605 setEffectiveUser(void)
607 leave_suid(); /* Run as non privilegied user */
613 if (geteuid() == 0) {
614 debug(0, 0) ("Squid is not safe to run as root! If you must\n");
615 debug(0, 0) ("start Squid as root, then you must configure\n");
616 debug(0, 0) ("it to run as a non-priveledged user with the\n");
617 debug(0, 0) ("'cache_effective_user' option in the config file.\n");
618 fatal("Don't run Squid as root, set 'cache_effective_user'!");
625 char pathbuf
[MAXPATHLEN
];
627 if (Config
.coredump_dir
) {
628 if (0 == strcmp("none", Config
.coredump_dir
)) {
630 } else if (chdir(Config
.coredump_dir
) == 0) {
631 debug(0, 1) ("Set Current Directory to %s\n", Config
.coredump_dir
);
634 debug(50, 0) ("chdir: %s: %s\n", Config
.coredump_dir
, xstrerror());
638 /* If we don't have coredump_dir or couldn't cd there, report current dir */
639 if (getcwd(pathbuf
, MAXPATHLEN
)) {
640 debug(0, 1) ("Current Directory is %s\n", pathbuf
);
642 debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
647 #include "DelayPools.h"
653 /* chroot if configured to run inside chroot */
655 if (Config
.chroot_dir
&& chroot(Config
.chroot_dir
)) {
656 fatal("failed to chroot");
659 if (opt_catch_signals
) {
660 squid_signal(SIGSEGV
, death
, SA_NODEFER
| SA_RESETHAND
);
661 squid_signal(SIGBUS
, death
, SA_NODEFER
| SA_RESETHAND
);
664 squid_signal(SIGPIPE
, SIG_IGN
, SA_RESTART
);
665 squid_signal(SIGCHLD
, sig_child
, SA_NODEFER
| SA_RESTART
);
669 if (icpPortNumOverride
!= 1)
670 Config
.Port
.icp
= (u_short
) icpPortNumOverride
;
672 _db_init(Config
.Log
.log
, Config
.debugOptions
);
674 fd_open(fileno(debug_log
), FD_LOG
, Config
.Log
.log
);
678 log_trace_init("/tmp/squid.alloc");
682 debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
688 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
689 debug(1, 0) ("Running as %s Windows System Service on %s\n", WIN32_Service_name
, WIN32_OS_string
);
690 debug(1, 0) ("Service command line is: %s\n", WIN32_Service_Command_Line
);
692 debug(1, 0) ("Running on %s\n",WIN32_OS_string
);
696 debug(1, 1) ("Process ID %d\n", (int) getpid());
698 debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD
);
702 debug(1, 1) ("With %d CRT stdio descriptors available\n", _getmaxstdio());
704 if (WIN32_Socks_initialized
)
705 debug(1, 1)("Windows sockets initialized\n");
709 if (!configured_once
)
710 disk_init(); /* disk_init must go before ipcache_init() */
730 authenticateInit(&Config
.authConfiguration
);
738 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
740 httpReplyInitModule(); /* must go before accepting replies */
758 malloc_debug(0, malloc_debug_level
);
762 if (!configured_once
) {
772 /* after this point we want to see the mallinfo() output */
774 mimeInit(Config
.mimeTablePathname
);
790 serverConnectionsOpen();
794 if (Config
.chroot_dir
)
797 if (!configured_once
)
798 writePidFile(); /* write PID file */
800 #ifdef _SQUID_LINUX_THREADS_
802 squid_signal(SIGQUIT
, rotate_logs
, SA_RESTART
);
804 squid_signal(SIGTRAP
, sigusr2_handle
, SA_RESTART
);
808 squid_signal(SIGUSR1
, rotate_logs
, SA_RESTART
);
810 squid_signal(SIGUSR2
, sigusr2_handle
, SA_RESTART
);
814 squid_signal(SIGHUP
, reconfigure
, SA_RESTART
);
816 squid_signal(SIGTERM
, shut_down
, SA_NODEFER
| SA_RESETHAND
| SA_RESTART
);
818 squid_signal(SIGINT
, shut_down
, SA_NODEFER
| SA_RESETHAND
| SA_RESTART
);
822 debug(1, 1) ("Ready to serve requests.\n");
824 if (!configured_once
) {
825 eventAdd("storeMaintain", storeMaintainSwapSpace
, NULL
, 1.0, 1);
827 if (Config
.onoff
.announce
)
828 eventAdd("start_announce", start_announce
, NULL
, 3600.0, 1);
830 eventAdd("ipcache_purgelru", ipcache_purgelru
, NULL
, 10.0, 1);
832 eventAdd("fqdncache_purgelru", fqdncache_purgelru
, NULL
, 15.0, 1);
836 eventAdd("cpuProfiling", xprof_event
, NULL
, 1.0, 1);
840 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools
, NULL
, 15.0, 1);
842 eventAdd("commCheckHalfClosed", commCheckHalfClosed
, NULL
, 1.0, false);
848 #if USE_WIN32_SERVICE
849 /* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */
850 extern "C" void WINAPI
851 SquidMain(int argc
, char **argv
)
854 main(int argc
, char **argv
)
858 int n
; /* # of GC'd objects */
863 sbrk_start
= sbrk(0);
868 if (FD_SETSIZE
< Squid_MaxFD
)
869 Squid_MaxFD
= FD_SETSIZE
;
872 #ifdef USE_WIN32_SERVICE
874 if (WIN32_Subsystem_Init(&argc
, &argv
))
882 if ((WIN32_init_err
= WIN32_Subsystem_Init()))
883 return WIN32_init_err
;
889 /* call mallopt() before anything else */
892 /* Round up all sizes to a multiple of this */
893 mallopt(M_GRAIN
, 16);
897 /* biggest size that is considered a small block */
898 mallopt(M_MXFAST
, 256);
902 /* allocate this many small blocks at once */
903 mallopt(M_NLBLKS
, 32);
906 #endif /* HAVE_MALLOPT */
909 * The plan here is to set the umask to 007 (deny others for
910 * read,write,execute), but only if the umask is not already
911 * set. Unfortunately, there is no way to get the current
912 * umask value without setting it.
914 oldmask
= umask(S_IRWXO
);
919 memset(&local_addr
, '\0', sizeof(struct in_addr
));
921 safe_inet_addr(localhost
, &local_addr
);
923 memset(&any_addr
, '\0', sizeof(struct in_addr
));
925 safe_inet_addr("0.0.0.0", &any_addr
);
927 memset(&no_addr
, '\0', sizeof(struct in_addr
));
929 safe_inet_addr("255.255.255.255", &no_addr
);
931 squid_srandom(time(NULL
));
935 squid_start
= current_time
;
937 failure_notify
= fatal_dump
;
939 #if USE_WIN32_SERVICE
941 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
945 mainParseOptions(argc
, argv
);
947 #if USE_WIN32_SERVICE
949 if (opt_install_service
) {
950 WIN32_InstallService();
954 if (opt_remove_service
) {
955 WIN32_RemoveService();
959 if (opt_command_line
) {
960 WIN32_SetServiceCommandLine();
966 /* parse configuration file
967 * note: in "normal" case this used to be called from mainInitialize() */
972 ConfigFile
= xstrdup(DefaultConfigFile
);
974 assert(!configured_once
);
986 eventInit(); /* eventInit() is required for config parsing */
988 storeFsInit(); /* required for config parsing */
990 /* Shouldn't be needed for config parsing, but have not audited for such */
991 StoreFileSystem::SetupAllFs();
993 authenticateSchemeInit(); /* required for config parsign */
995 parse_err
= parseConfigFile(ConfigFile
);
997 if (opt_parse_cfg_only
)
998 #if USE_WIN32_SERVICE
1009 if (-1 == opt_send_signal
)
1010 if (checkRunningPid())
1027 /* send signal to running copy and exit */
1028 if (opt_send_signal
!= -1) {
1029 /* chroot if configured to run inside chroot */
1031 if (Config
.chroot_dir
&& chroot(Config
.chroot_dir
)) {
1032 fatal("failed to chroot");
1039 if (opt_create_swap_dirs
) {
1040 /* chroot if configured to run inside chroot */
1042 if (Config
.chroot_dir
&& chroot(Config
.chroot_dir
)) {
1043 fatal("failed to chroot");
1047 debug(0, 0) ("Creating Swap Directories\n");
1048 storeCreateSwapDirectories();
1049 #if USE_WIN32_SERVICE
1064 if (opt_catch_signals
)
1065 for (n
= Squid_MaxFD
; n
> 2; n
--)
1068 /* init comm module */
1073 if (opt_no_daemon
) {
1074 /* we have to init fdstat here. */
1075 fd_open(0, FD_LOG
, "stdin");
1076 fd_open(1, FD_LOG
, "stdout");
1077 fd_open(2, FD_LOG
, "stderr");
1080 #if USE_WIN32_SERVICE
1082 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
1088 #if USE_WIN32_SERVICE
1090 WIN32_svcstatusupdate(SERVICE_RUNNING
, 0);
1097 if (do_reconfigure
) {
1100 #if defined(_SQUID_MSWIN_) && defined(_DEBUG)
1102 } else if (do_debug
) {
1107 } else if (do_rotate
) {
1110 } else if (do_shutdown
) {
1111 time_t wait
= do_shutdown
> 0 ? (int) Config
.shutdownLifetime
: 0;
1112 debug(1, 1) ("Preparing for shutdown after %d requests\n",
1113 statCounter
.client_http
.requests
);
1114 debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
1118 #if USE_WIN32_SERVICE
1120 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, (wait
+ 1) * 1000);
1123 serverConnectionsClose();
1124 eventAdd("SquidShutdown", SquidShutdown
, NULL
, (double) (wait
+ 1), 1);
1128 int loop_delay
= eventNextTime();
1133 /* Attempt any pending storedir IO */
1136 comm_calliocallback();
1138 /* and again to deal with indirectly queued events
1139 * resulting from the first call. These are usually
1140 * callbacks and should be dealt with immediately.
1142 if (comm_iocallbackpending())
1143 comm_calliocallback();
1145 switch (comm_select(loop_delay
)) {
1148 errcount
= 0; /* reset if successful */
1153 debug(1, 0) ("Select loop Error. Retry %d\n", errcount
);
1156 fatal_dump("Select Loop failed!");
1164 SquidShutdown(NULL
);
1169 fatal_dump("MAIN: Internal error -- this should never happen.");
1176 #if USE_WIN32_SERVICE
1192 if (strcmp(Config
.pidFilename
, "none") == 0) {
1193 debug(0, 1) ("No pid_filename specified. Trusting you know what you are doing.\n");
1196 pid
= readPidFile();
1199 #if USE_WIN32_SERVICE
1201 if (opt_signal_service
) {
1202 WIN32_sendSignal(opt_send_signal
);
1205 #ifdef _SQUID_MSWIN_
1207 fprintf(stderr
, "%s: ERROR: Could not send ", appname
);
1208 fprintf(stderr
, "signal to Squid Service:\n");
1209 fprintf(stderr
, "missing -n command line switch.\n");
1218 if (kill(pid
, opt_send_signal
) &&
1219 /* ignore permissions if just running check */
1220 !(opt_send_signal
== 0 && errno
== EPERM
)) {
1221 fprintf(stderr
, "%s: ERROR: Could not send ", appname
);
1222 fprintf(stderr
, "signal %d to process %d: %s\n",
1223 opt_send_signal
, (int) pid
, xstrerror());
1227 fprintf(stderr
, "%s: ERROR: No running copy\n", appname
);
1231 /* signal successfully sent */
1235 #ifndef _SQUID_MSWIN_
1237 * This function is run when Squid is in daemon mode, just
1238 * before the parent forks and starts up the child process.
1239 * It can be used for admin-specific tasks, such as notifying
1240 * someone that Squid is (re)started.
1243 mainStartScript(const char *prog
)
1245 char script
[SQUID_MAXPATHLEN
];
1250 xstrncpy(script
, prog
, MAXPATHLEN
);
1252 if ((t
= strrchr(script
, '/'))) {
1254 sl
= strlen(script
);
1257 xstrncpy(&script
[sl
], squid_start_script
, MAXPATHLEN
- sl
);
1259 if ((cpid
= fork()) == 0) {
1261 execl(script
, squid_start_script
, 0);
1267 rpid
= wait3(&status
, 0, NULL
);
1271 rpid
= waitpid(-1, &status
, 0);
1274 } while (rpid
!= cpid
);
1278 #endif /* _SQUID_MSWIN_ */
1281 checkRunningPid(void)
1285 pid
= readPidFile();
1290 if (kill(pid
, 0) < 0)
1293 debugs(0, 0, "Squid is already running! Process ID " << pid
);
1299 watch_child(char *argv
[])
1301 #ifndef _SQUID_MSWIN_
1318 if (*(argv
[0]) == '(')
1321 openlog(appname
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1323 if ((pid
= fork()) < 0)
1324 syslog(LOG_ALERT
, "fork failed: %s", xstrerror());
1329 syslog(LOG_ALERT
, "setsid failed: %s", xstrerror());
1335 if ((i
= open("/dev/tty", O_RDWR
| O_TEXT
)) >= 0) {
1336 ioctl(i
, TIOCNOTTY
, NULL
);
1344 * RBCOLLINS - if cygwin stackdumps when squid is run without
1345 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1346 * 1.1.3. execvp had a bit overflow error in a loop..
1348 /* Connect stdio to /dev/null in daemon mode */
1349 nullfd
= open("/dev/null", O_RDWR
| O_TEXT
);
1352 fatalf("/dev/null: %s\n", xstrerror());
1356 if (opt_debug_stderr
< 0) {
1361 /* Close all else */
1362 for (i
= 3; i
< Squid_MaxFD
; i
++)
1366 mainStartScript(argv
[0]);
1368 if ((pid
= fork()) == 0) {
1370 openlog(appname
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1371 prog
= xstrdup(argv
[0]);
1372 argv
[0] = xstrdup("(squid)");
1374 syslog(LOG_ALERT
, "execvp failed: %s", xstrerror());
1378 openlog(appname
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1380 syslog(LOG_NOTICE
, "Squid Parent: child process %d started", pid
);
1384 squid_signal(SIGINT
, SIG_IGN
, SA_RESTART
);
1388 pid
= wait3(&status
, 0, NULL
);
1392 pid
= waitpid(-1, &status
, 0);
1398 if (WIFEXITED(status
)) {
1400 "Squid Parent: child process %d exited with status %d",
1401 pid
, WEXITSTATUS(status
));
1402 } else if (WIFSIGNALED(status
)) {
1404 "Squid Parent: child process %d exited due to signal %d",
1405 pid
, WTERMSIG(status
));
1407 syslog(LOG_NOTICE
, "Squid Parent: child process %d exited", pid
);
1410 if (stop
- start
< 10)
1415 if (failcount
== 5) {
1416 syslog(LOG_ALERT
, "Exiting due to repeated, frequent failures");
1420 if (WIFEXITED(status
))
1421 if (WEXITSTATUS(status
) == 0)
1424 if (WIFSIGNALED(status
)) {
1425 switch (WTERMSIG(status
)) {
1436 squid_signal(SIGINT
, SIG_DFL
, SA_RESTART
);
1441 #endif /* _SQUID_MSWIN_ */
1445 SquidShutdown(void *unused
)
1447 #if USE_WIN32_SERVICE
1448 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
1451 debug(1, 1) ("Shutting down...\n");
1461 externalAclShutdown();
1462 icpConnectionClose();
1469 snmpConnectionClose();
1473 wccpConnectionClose();
1476 releaseServerSockets();
1477 commCloseAllSockets();
1480 DelayPools::FreePools();
1483 authenticateShutdown();
1488 #if USE_WIN32_SERVICE
1490 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
1493 storeDirSync(); /* Flush pending object writes/unlinks */
1494 storeDirWriteCleanLogs(0);
1497 storeDirSync(); /* Flush log writes */
1500 useragentLogClose();
1507 storeDirSync(); /* Flush log close */
1508 StoreFileSystem::FreeAllFs();
1509 #if PURIFY || XMALLOC_TRACE
1513 /*stmemFreeMemory(); */
1515 ipcacheFreeMemory();
1516 fqdncacheFreeMemory();
1518 clientdbFreeMemory();
1519 httpHeaderCleanModule();
1527 if (opt_no_daemon
) {
1542 xmalloc_find_leaks();
1544 debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total
);
1553 if (Config
.pidFilename
&& strcmp(Config
.pidFilename
, "none") != 0) {
1555 safeunlink(Config
.pidFilename
, 0);
1559 debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",