2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 01 Startup and Main Loop */
12 #include "AccessLogEntry.h"
13 //#include "acl/Acl.h"
14 #include "acl/forward.h"
15 #include "anyp/UriScheme.h"
16 #include "auth/Config.h"
17 #include "auth/Gadgets.h"
19 #include "base/RunnersRegistry.h"
20 #include "base/Subscription.h"
21 #include "base/TextException.h"
23 #include "CachePeer.h"
24 #include "client_db.h"
25 #include "client_side.h"
27 #include "CommandLine.h"
28 #include "compat/unistd.h"
29 #include "ConfigParser.h"
30 #include "CpuAffinity.h"
31 #include "debug/Messages.h"
32 #include "DiskIO/DiskIOModule.h"
33 #include "dns/forward.h"
34 #include "errorpage.h"
36 #include "EventLoop.h"
37 #include "ExternalACL.h"
39 #include "format/Token.h"
40 #include "fqdncache.h"
41 #include "fs/Module.h"
45 #include "http/Stream.h"
46 #include "HttpHeader.h"
47 #include "HttpReply.h"
48 #include "icmp/IcmpSquid.h"
49 #include "icmp/net_db.h"
53 #include "ipc/Coordinator.h"
55 #include "ipc/Strand.h"
58 #include "neighbors.h"
59 #include "parser/Tokenizer.h"
62 #include "PeerSelectState.h"
66 #include "sbuf/Stream.h"
67 #include "SBufStatsAction.h"
68 #include "SquidConfig.h"
70 #include "StatCounters.h"
72 #include "store/Disks.h"
73 #include "store_log.h"
74 #include "StoreFileSystem.h"
75 #include "time/Engine.h"
78 #include "windows_service.h"
81 #include "adaptation/Config.h"
84 #include "adaptation/ecap/Config.h"
87 #include "adaptation/icap/Config.h"
88 #include "adaptation/icap/icap_log.h"
91 #include "ClientDelayConfig.h"
94 #include "DelayPools.h"
96 #if USE_LOADABLE_MODULES
97 #include "LoadableModules.h"
100 #include "ssl/context_storage.h"
101 #include "ssl/helper.h"
104 #include "adaptation/icap/Config.h"
107 #include "adaptation/ecap/Config.h"
110 #include "adaptation/Config.h"
121 #include <sys/wait.h>
124 #if USE_WIN32_SERVICE
127 static int opt_install_service
= FALSE
;
128 static int opt_remove_service
= FALSE
;
129 static int opt_command_line
= FALSE
;
130 void WIN32_svcstatusupdate(DWORD
, DWORD
);
131 void WINAPI
WIN32_svcHandler(DWORD
);
134 static int opt_signal_service
= FALSE
;
135 static char *opt_syslog_facility
= nullptr;
136 static int icpPortNumOverride
= 1; /* Want to detect "-u 0" */
137 static int configured_once
= 0;
139 static int malloc_debug_level
= 0;
141 static volatile int do_reconfigure
= 0;
142 static volatile int do_rotate
= 0;
143 static volatile int do_shutdown
= 0;
144 static volatile int do_revive_kids
= 0;
145 static volatile int shutdown_status
= EXIT_SUCCESS
;
146 static volatile int do_handle_stopped_child
= 0;
148 static int RotateSignal
= -1;
149 static int ReconfigureSignal
= -1;
150 static int ShutdownSignal
= -1;
151 static int ReviveKidsSignal
= -1;
153 static void mainRotate(void);
154 static void mainReconfigureStart(void);
155 static void mainReconfigureFinish(void*);
156 static void mainInitialize(void);
157 static void usage(void);
158 static void mainHandleCommandLineOption(const int optId
, const char *optValue
);
159 static void sendSignal(void);
160 static void serverConnectionsOpen(void);
161 static void serverConnectionsClose(void);
162 static void watch_child(const CommandLine
&);
163 static void setEffectiveUser(void);
164 static void SquidShutdown(void);
165 static void mainSetCwd(void);
168 static const char *squid_start_script
= "squid_start";
172 #include "test_access.c"
175 /** temporary thunk across to the unrefactored store interface */
177 class StoreRootEngine
: public AsyncEngine
181 int checkEvents(int) override
{
182 Store::Root().callback();
187 class SignalEngine
: public AsyncEngine
191 int checkEvents(int timeout
) override
;
194 static void StopEventLoop(void *) {
195 if (EventLoop::Running
)
196 EventLoop::Running
->stop();
199 static void FinalShutdownRunners(void *) {
200 RunRegisteredHere(RegisteredRunner::endingShutdown
);
202 // XXX: this should be a Runner.
204 /* detach the auth components (only do this on full shutdown) */
205 Auth::Scheme::FreeAll();
208 eventAdd("SquidTerminate", &StopEventLoop
, nullptr, 0, 1, false);
211 void doShutdown(time_t wait
);
212 void handleStoppedChild();
216 SignalEngine::checkEvents(int)
219 mainReconfigureStart();
222 else if (do_shutdown
)
223 doShutdown(do_shutdown
> 0 ? (int) Config
.shutdownLifetime
: 0);
224 if (do_handle_stopped_child
)
225 handleStoppedChild();
229 /// Decides whether the signal-controlled action X should be delayed, canceled,
230 /// or executed immediately. Clears do_X (via signalVar) as needed.
232 AvoidSignalAction(const char *description
, volatile int &signalVar
)
234 const char *avoiding
= "delaying";
235 const char *currentEvent
= "none";
237 currentEvent
= "shutdown";
238 avoiding
= "canceling";
239 // do not avoid repeated shutdown signals
240 // which just means the user wants to skip/abort shutdown timeouts
241 if (strcmp(currentEvent
, description
) == 0)
245 else if (!configured_once
)
246 currentEvent
= "startup";
247 else if (reconfiguring
)
248 currentEvent
= "reconfiguration";
251 return false; // do not avoid (i.e., execute immediately)
252 // the caller may produce a signal-specific debugging message
255 debugs(1, DBG_IMPORTANT
, avoiding
<< ' ' << description
<<
256 " request during " << currentEvent
);
261 SignalEngine::doShutdown(time_t wait
)
263 if (AvoidSignalAction("shutdown", do_shutdown
))
266 debugs(1, Important(2), "Preparing for shutdown after " << statCounter
.client_http
.requests
<< " requests");
267 debugs(1, Important(3), "Waiting " << wait
<< " seconds for active connections to finish");
270 // Already a shutdown signal has received and shutdown is in progress.
271 // Shutdown as soon as possible.
276 /* run the closure code which can be shared with reconfigure */
277 serverConnectionsClose();
279 RunRegisteredHere(RegisteredRunner::startShutdown
);
282 #if USE_WIN32_SERVICE
283 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, (wait
+ 1) * 1000);
286 eventAdd("SquidShutdown", &FinalShutdownRunners
, this, (double) (wait
+ 1), 1, false);
290 SignalEngine::handleStoppedChild()
292 // no AvoidSignalAction() call: This code can run at any time because it
293 // does not depend on Squid state. It does not need debugging because it
294 // handles an "internal" signal, not an external/admin command.
295 do_handle_stopped_child
= 0;
301 pid
= WaitForAnyPid(status
, WNOHANG
);
310 while (pid
> 0 || (pid
< 0 && errno
== EINTR
));
319 "Usage: %s [-cdzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]"
320 #if USE_WIN32_SERVICE
321 "[-ir] [-O CommandLine]"
324 " -h | --help Print help message.\n"
325 " -v | --version Print version details.\n"
327 " -a port Specify HTTP port number (default: %d).\n"
328 " -d level Write debugging to stderr also.\n"
329 " -f file Use given config-file instead of\n"
331 #if USE_WIN32_SERVICE
332 " -i Installs as a Windows Service (see -n option).\n"
334 " -k reconfigure|rotate|shutdown|"
338 "interrupt|kill|debug|check|parse\n"
339 " Parse configuration file, then send signal to \n"
340 " running copy (except -k parse) and exit.\n"
341 " -n name Specify service name to use for service operations\n"
342 " default is: " APP_SHORTNAME
".\n"
343 #if USE_WIN32_SERVICE
344 " -r Removes a Windows Service (see -n option).\n"
346 " -s | -l facility\n"
347 " Enable logging to syslog.\n"
348 " -u port Specify ICP port number (default: %d), disable with 0.\n"
349 " -z Create missing swap directories and then exit.\n"
350 " -C Do not catch fatal signals.\n"
351 " -D OBSOLETE. Scheduled for removal.\n"
352 " -F Don't serve any requests until store is rebuilt.\n"
353 " -N Master process runs in foreground and is a worker. No kids.\n"
355 " Master process runs in foreground and creates worker kids.\n"
357 " Play a given SMP kid process role, with a given ID. Do not use\n"
358 " this option. It is meant for the master process use only.\n"
359 #if USE_WIN32_SERVICE
361 " Set Windows Service Command line options in Registry.\n"
363 " -R Do not set REUSEADDR on port.\n"
364 " -S Double-check swap during rebuild.\n"
365 " -X Force full debugging.\n"
366 " Add -d9 to also write full debugging to stderr.\n"
367 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
368 APP_SHORTNAME
, CACHE_HTTP_PORT
, DEFAULT_CONFIG_FILE
, CACHE_ICP_PORT
);
372 /// CommandLine option IDs for --long options that lack a short (-x) equivalent
374 // The absolute values do not matter except that the following values should
375 // not be used: Values below 2 are for special getopt_long(3) use cases, and
376 // values in the [33,126] range are reserved for short options (-x).
382 // TODO: consider prefixing with ':' for better logging
383 // (distinguish missing required argument cases)
384 static const char *shortOpStr
=
385 #if USE_WIN32_SERVICE
388 "CDFNRSYXa:d:f:hk:m::n:sl:u:vz?";
391 static struct option squidOptions
[] = {
392 {"foreground", no_argument
, nullptr, optForeground
},
393 {"kid", required_argument
, nullptr, optKid
},
394 {"help", no_argument
, nullptr, 'h'},
395 {"version", no_argument
, nullptr, 'v'},
396 {nullptr, 0, nullptr, 0}
399 // handle a command line parameter
401 mainHandleCommandLineOption(const int optId
, const char *optValue
)
407 * Unset/disable global option for catchign signals. opt_catch_signals */
408 opt_catch_signals
= 0;
413 * OBSOLETE: WAS: override to prevent optional startup DNS tests. */
414 debugs(1,DBG_CRITICAL
, "WARNING: -D command-line option is obsolete.");
419 * Set global option for foreground rebuild. opt_foreground_rebuild */
420 opt_foreground_rebuild
= 1;
425 * Set global option for 'no_daemon' mode. opt_no_daemon */
429 #if USE_WIN32_SERVICE
433 * Set global option. opt_command_lin and WIN32_Command_Line */
434 opt_command_line
= 1;
435 WIN32_Command_Line
= xstrdup(optValue
);
441 * Unset/disable global option opt_reuseaddr */
447 * Set global option opt_store_doublecheck */
448 opt_store_doublecheck
= 1;
453 * Force full debugging */
454 Debug::parseOptions("rotate=0 ALL,9");
455 Debug::override_X
= 1;
456 sigusr2_handle(SIGUSR2
);
461 * Set global option opt_reload_hit_only */
462 opt_reload_hit_only
= 1;
465 #if USE_WIN32_SERVICE
469 * Set global option opt_install_service (to TRUE) */
470 opt_install_service
= TRUE
;
477 * Add optional HTTP port as given following the option */
478 char *port
= xstrdup(optValue
);
479 // use a copy to avoid optValue modification
487 * debugs() messages with the given debugging level (and the more
488 * important ones) should be written to stderr */
489 Debug::ResetStderrLevel(xatoi(optValue
));
494 * Load the file given instead of the default squid.conf. */
496 ConfigFile
= xstrdup(optValue
);
501 * Run the administrative action given following the option */
503 /** \li When it is missing or an unknown option display the usage help. */
504 if (!optValue
|| strlen(optValue
) < 1)
507 else if (!strncmp(optValue
, "reconfigure", strlen(optValue
)))
508 /** \li On reconfigure send SIGHUP. */
509 opt_send_signal
= SIGHUP
;
510 else if (!strncmp(optValue
, "rotate", strlen(optValue
)))
511 /** \li On rotate send SIGQUIT or SIGUSR1. */
512 #if defined(_SQUID_LINUX_THREADS_)
513 opt_send_signal
= SIGQUIT
;
515 opt_send_signal
= SIGUSR1
;
518 else if (!strncmp(optValue
, "debug", strlen(optValue
)))
519 /** \li On debug send SIGTRAP or SIGUSR2. */
520 #if defined(_SQUID_LINUX_THREADS_)
521 opt_send_signal
= SIGTRAP
;
523 opt_send_signal
= SIGUSR2
;
526 else if (!strncmp(optValue
, "shutdown", strlen(optValue
)))
527 /** \li On shutdown send SIGTERM. */
528 opt_send_signal
= SIGTERM
;
529 else if (!strncmp(optValue
, "interrupt", strlen(optValue
)))
530 /** \li On interrupt send SIGINT. */
531 opt_send_signal
= SIGINT
;
532 else if (!strncmp(optValue
, "kill", strlen(optValue
)))
533 // XXX: In SMP mode, uncatchable SIGKILL only kills the master process
534 /** \li On kill send SIGKILL. */
535 opt_send_signal
= SIGKILL
;
539 else if (!strncmp(optValue
, "restart", strlen(optValue
)))
540 /** \li On restart send SIGTTIN. (exit and restart by parent) */
541 opt_send_signal
= SIGTTIN
;
545 else if (!strncmp(optValue
, "check", strlen(optValue
)))
546 /** \li On check send 0 / SIGNULL. */
547 opt_send_signal
= 0; /* SIGNULL */
548 else if (!strncmp(optValue
, "parse", strlen(optValue
)))
549 /** \li On parse set global flag to re-parse the config file only. */
550 opt_parse_cfg_only
= 1;
554 // Cannot use cache.log: use stderr for important messages (by default)
555 // and stop expecting a Debug::UseCacheLog() call.
556 Debug::EnsureDefaultStderrLevel(DBG_IMPORTANT
);
557 Debug::BanCacheLogUse();
562 * Set global malloc_debug_level to the value given following the option.
563 * if none is given it toggles the xmalloc_trace option on/off */
566 malloc_debug_level
= xatoi(optValue
);
568 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
576 * Set global option opt_signal_service (to true).
577 * Stores the additional parameter given in global service_name */
578 if (optValue
&& *optValue
!= '\0') {
579 const SBuf
t(optValue
);
580 ::Parser::Tokenizer
tok(t
);
581 const CharacterSet chr
= CharacterSet::ALPHA
+CharacterSet::DIGIT
;
582 if (!tok
.prefix(service_name
, chr
))
583 fatalf("Expected alphanumeric service name for the -n option but got: %s", optValue
);
585 fatalf("Garbage after alphanumeric service name in the -n option value: %s", optValue
);
586 if (service_name
.length() > 32)
587 fatalf("Service name (-n option) must be limited to 32 characters but got %u", service_name
.length());
588 opt_signal_service
= true;
590 fatal("A service name is required for the -n option");
594 #if USE_WIN32_SERVICE
598 * Set global option opt_remove_service (to TRUE) */
599 opt_remove_service
= TRUE
;
607 * Stores the syslog facility name in global opt_syslog_facility
608 * then performs actions for -s option. */
609 xfree(opt_syslog_facility
); // ignore any previous options sent
610 opt_syslog_facility
= xstrdup(optValue
);
611 Debug::ConfigureSyslog(opt_syslog_facility
);
616 * Initialize the syslog for output */
617 Debug::ConfigureSyslog(opt_syslog_facility
);
622 * Store the ICP port number given in global option icpPortNumOverride
623 * ensuring its a positive number. */
624 icpPortNumOverride
= atoi(optValue
);
626 if (icpPortNumOverride
< 0)
627 icpPortNumOverride
= 0;
633 * Display squid version and build information. Then exit. */
634 printf("Squid Cache: Version %s\n",version_string
);
635 printf("Service Name: " SQUIDSBUFPH
"\n", SQUIDSBUFPRINT(service_name
));
636 if (strlen(SQUID_BUILD_INFO
))
637 printf("%s\n",SQUID_BUILD_INFO
);
639 printf("\nThis binary uses %s. ", OpenSSL_version(OPENSSL_VERSION
));
640 #if OPENSSL_VERSION_MAJOR < 3
641 printf("For legal restrictions on distribution see https://www.openssl.org/source/license.html\n\n");
644 printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS
);
646 #if USE_WIN32_SERVICE
648 printf("Compiled as Windows System Service.\n");
658 * Request cache_dir initialization */
659 opt_create_swap_dirs
= 1;
660 // We will use cache.log, but this command is often executed on the
661 // command line, so use stderr to show important messages (by default).
662 // TODO: Generalize/fix this -z-specific and sometimes faulty logic with
663 // "use stderr when it is a tty [until we GoIntoBackground()]" logic.
664 Debug::EnsureDefaultStderrLevel(DBG_IMPORTANT
);
668 /** \par --foreground
669 * Set global option opt_foreground */
674 // already processed in ConfigureCurrentKid()
682 /** \par h,?, or unknown
683 * \copydoc usage() */
699 signal(sig
, rotate_logs
);
709 ReconfigureSignal
= sig
;
713 signal(sig
, reconfigure
);
719 master_revive_kids(int sig
)
721 ReviveKidsSignal
= sig
;
722 do_revive_kids
= true;
726 signal(sig
, master_revive_kids
);
731 /// Shutdown signal handler for master process
733 master_shutdown(int sig
)
736 ShutdownSignal
= sig
;
740 signal(sig
, master_shutdown
);
749 do_shutdown
= sig
== SIGINT
? -1 : 1;
750 ShutdownSignal
= sig
;
753 shutdown_status
= EXIT_FAILURE
;
756 #if !defined(_SQUID_WINDOWS_) && !defined(HAVE_SIGACTION)
757 signal(sig
, shut_down
);
764 do_handle_stopped_child
= 1;
766 #if !defined(_SQUID_WINDOWS_) && !defined(HAVE_SIGACTION)
767 signal(sig
, sig_child
);
774 serverConnectionsOpen(void)
776 // start various proxying services if we are responsible for them
777 if (IamWorkerProcess()) {
778 clientOpenListenSockets();
782 Acl::Node::Initialize();
788 serverConnectionsClose(void)
790 assert(shutting_down
|| reconfiguring
);
792 if (IamWorkerProcess()) {
793 clientConnectionsClose();
794 icpConnectionShutdown();
800 mainReconfigureStart(void)
802 if (AvoidSignalAction("reconfiguration", do_reconfigure
))
805 debugs(1, DBG_IMPORTANT
, "Reconfiguring Squid Cache (version " << version_string
<< ")...");
808 RunRegisteredHere(RegisteredRunner::startReconfigure
);
810 // Initiate asynchronous closing sequence
811 serverConnectionsClose();
814 Ssl::TheGlobalContextStorage().reconfigureStart();
819 externalAclShutdown();
820 storeDirCloseSwapLogs();
826 Security::CloseLogs();
828 eventAdd("mainReconfigureFinish", &mainReconfigureFinish
, nullptr, 0, 1,
832 /// error message to log when Configuration::Parse() fails
834 ConfigurationFailureMessage()
837 out
<< (reconfiguring
? "re" : "");
838 out
<< "configuration failure: " << CurrentException
;
839 if (!opt_parse_cfg_only
)
840 out
<< Debug::Extra
<< "advice: Run 'squid -k parse' and check for ERRORs.";
845 mainReconfigureFinish(void *)
847 debugs(1, 3, "finishing reconfiguring");
850 enter_suid(); /* root to read config file */
852 // we may have disabled the need for PURGE
853 if (Config2
.onoff
.enable_purge
)
854 Config2
.onoff
.enable_purge
= 2;
856 const int oldWorkers
= Config
.workers
;
859 Configuration::Parse();
861 // for now any errors are a fatal condition...
862 fatal(ConfigurationFailureMessage().c_str());
865 if (oldWorkers
!= Config
.workers
) {
866 debugs(1, DBG_CRITICAL
, "WARNING: Changing 'workers' (from " <<
867 oldWorkers
<< " to " << Config
.workers
<<
868 ") requires a full restart. It has been ignored by reconfigure.");
869 Config
.workers
= oldWorkers
;
872 RunRegisteredHere(RegisteredRunner::syncConfig
);
874 if (IamPrimaryProcess())
876 CpuAffinityReconfigure();
878 setUmask(Config
.umask
);
880 Debug::UseCacheLog();
881 ipcache_restart(); /* clear stuck entries */
882 fqdncache_restart(); /* sigh, fqdncache too */
884 errorInitialize(); /* reload error pages */
887 #if USE_LOADABLE_MODULES
888 LoadableModulesConfigure(Config
.loadable_module_names
);
892 bool enableAdaptation
= false;
894 Adaptation::Icap::TheConfig
.finalize();
895 enableAdaptation
= Adaptation::Icap::TheConfig
.onoff
|| enableAdaptation
;
898 Adaptation::Ecap::TheConfig
.finalize(); // must be after we load modules
899 enableAdaptation
= Adaptation::Ecap::TheConfig
.onoff
|| enableAdaptation
;
901 Adaptation::Config::Finalize(enableAdaptation
);
904 Security::OpenLogs();
911 Ssl::Helper::Reconfigure();
914 Ssl::CertValidationHelper::Reconfigure();
917 redirectReconfigure();
919 authenticateInit(&Auth::TheConfig
.schemes
);
923 serverConnectionsOpen();
927 storeDirOpenSwapLogs();
929 mimeInit(Config
.mimeTablePathname
);
935 Config
.ClientDelay
.finalize();
944 if (AvoidSignalAction("log rotation", do_rotate
))
950 authenticateRotate();
952 externalAclShutdown();
954 _db_rotate_log(); /* cache.log */
955 storeDirWriteCleanLogs(1);
956 storeLogRotate(); /* store.log */
957 accessLogRotate(); /* access.log */
958 Security::RotateLogs();
960 icapLogRotate(); /*icap.log*/
965 authenticateInit(&Auth::TheConfig
.schemes
);
971 setEffectiveUser(void)
974 leave_suid(); /* Run as non privilegied user */
980 if (geteuid() == 0) {
981 debugs(0, DBG_CRITICAL
, "Squid is not safe to run as root! If you must");
982 debugs(0, DBG_CRITICAL
, "start Squid as root, then you must configure");
983 debugs(0, DBG_CRITICAL
, "it to run as a non-privileged user with the");
984 debugs(0, DBG_CRITICAL
, "'cache_effective_user' option in the config file.");
985 fatal("Don't run Squid as root, set 'cache_effective_user'!");
989 /// changes working directory, providing error reporting
991 mainChangeDir(const char *dir
)
997 debugs(50, DBG_CRITICAL
, "ERROR: cannot change current directory to " << dir
<<
998 ": " << xstrerr(xerrno
));
1002 /// Hack: Have we called chroot()? This exposure is needed because some code has
1003 /// to open the same files before and after chroot()
1004 bool Chrooted
= false;
1006 /// set the working directory.
1010 if (Config
.chroot_dir
&& !Chrooted
) {
1013 if (chroot(Config
.chroot_dir
) != 0) {
1015 fatalf("chroot to %s failed: %s", Config
.chroot_dir
, xstrerr(xerrno
));
1018 if (!mainChangeDir("/"))
1019 fatalf("chdir to / after chroot to %s failed", Config
.chroot_dir
);
1022 if (Config
.coredump_dir
&& strcmp("none", Config
.coredump_dir
) != 0) {
1023 if (mainChangeDir(Config
.coredump_dir
)) {
1024 debugs(0, Important(4), "Set Current Directory to " << Config
.coredump_dir
);
1029 /* If we don't have coredump_dir or couldn't cd there, report current dir */
1030 char pathbuf
[MAXPATHLEN
];
1031 if (getcwd(pathbuf
, MAXPATHLEN
)) {
1032 debugs(0, DBG_IMPORTANT
, "Current Directory is " << pathbuf
);
1035 debugs(50, DBG_CRITICAL
, "WARNING: Can't find current directory, getcwd: " << xstrerr(xerrno
));
1040 mainInitialize(void)
1042 if (opt_catch_signals
) {
1043 squid_signal(SIGSEGV
, death
, SA_NODEFER
| SA_RESETHAND
);
1044 squid_signal(SIGBUS
, death
, SA_NODEFER
| SA_RESETHAND
);
1047 squid_signal(SIGPIPE
, SIG_IGN
, SA_RESTART
);
1048 squid_signal(SIGCHLD
, sig_child
, SA_NODEFER
| SA_RESTART
);
1049 squid_signal(SIGHUP
, reconfigure
, SA_RESTART
);
1053 if (icpPortNumOverride
!= 1)
1054 Config
.Port
.icp
= (unsigned short) icpPortNumOverride
;
1056 debugs(1, DBG_CRITICAL
, "Starting Squid Cache version " << version_string
<< " for " << CONFIG_HOST_TYPE
<< "...");
1057 debugs(1, Critical(5), "Service Name: " << service_name
);
1060 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
1061 debugs(1, DBG_CRITICAL
, "Service command line is: " << WIN32_Service_Command_Line
);
1063 debugs(1, DBG_CRITICAL
, "Running on " << WIN32_OS_string
);
1066 debugs(1, Important(6), "Process ID " << getpid());
1068 debugs(1, Important(7), "Process Roles:" << ProcessRoles());
1071 debugs(1, Important(8), "With " << Squid_MaxFD
<< " file descriptors available");
1075 debugs(1, DBG_IMPORTANT
, "With " << _getmaxstdio() << " CRT stdio descriptors available");
1077 if (WIN32_Socks_initialized
)
1078 debugs(1, DBG_IMPORTANT
, "Windows sockets initialized");
1080 if (WIN32_OS_version
> _WIN_OS_WINNT
) {
1081 WIN32_IpAddrChangeMonitorInit();
1095 Ssl::Helper::Init();
1099 Ssl::CertValidationHelper::Init();
1104 authenticateInit(&Auth::TheConfig
.schemes
);
1108 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
1114 Security::OpenLogs();
1122 malloc_debug(0, malloc_debug_level
);
1126 if (unlinkdNeeded())
1133 mimeInit(Config
.mimeTablePathname
);
1139 FwdState::initModule();
1140 SBufStatsAction::RegisterWithCacheManager();
1142 AsyncJob::RegisterWithCacheManager();
1144 /* These use separate calls so that the comm loops can eventually
1150 // TODO: pconn is a good candidate for new-style registration
1151 // PconnModule::GetInstance()->registerWithCacheManager();
1152 // moved to PconnModule::PconnModule()
1154 serverConnectionsOpen();
1158 // neighborsRegisterWithCacheManager(); //moved to neighbors_init()
1160 if (Config
.chroot_dir
)
1163 #if defined(_SQUID_LINUX_THREADS_)
1165 squid_signal(SIGQUIT
, rotate_logs
, SA_RESTART
);
1167 squid_signal(SIGTRAP
, sigusr2_handle
, SA_RESTART
);
1171 squid_signal(SIGUSR1
, rotate_logs
, SA_RESTART
);
1173 squid_signal(SIGUSR2
, sigusr2_handle
, SA_RESTART
);
1177 squid_signal(SIGTERM
, shut_down
, SA_RESTART
);
1179 squid_signal(SIGINT
, shut_down
, SA_RESTART
);
1183 squid_signal(SIGTTIN
, shut_down
, SA_RESTART
);
1187 #if USE_LOADABLE_MODULES
1188 LoadableModulesConfigure(Config
.loadable_module_names
);
1192 bool enableAdaptation
= false;
1194 // We can remove this dependency on specific adaptation mechanisms
1195 // if we create a generic Registry of such mechanisms. Should we?
1197 Adaptation::Icap::TheConfig
.finalize();
1198 enableAdaptation
= Adaptation::Icap::TheConfig
.onoff
|| enableAdaptation
;
1201 Adaptation::Ecap::TheConfig
.finalize(); // must be after we load modules
1202 enableAdaptation
= Adaptation::Ecap::TheConfig
.onoff
|| enableAdaptation
;
1204 // must be the last adaptation-related finalize
1205 Adaptation::Config::Finalize(enableAdaptation
);
1209 Config
.ClientDelay
.finalize();
1212 eventAdd("storeMaintain", Store::Maintain
, nullptr, 1.0, 1);
1214 eventAdd("ipcache_purgelru", ipcache_purgelru
, nullptr, 10.0, 1);
1216 eventAdd("fqdncache_purgelru", fqdncache_purgelru
, nullptr, 15.0, 1);
1218 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools
, nullptr, 15.0, 1);
1220 configured_once
= 1;
1226 // ignore recursive calls to avoid termination loops
1227 static bool terminating
= false;
1232 debugs(1, DBG_CRITICAL
, "FATAL: Dying after an undetermined failure" << CurrentExceptionExtra
);
1234 Debug::PrepareToDie();
1238 /// unsafe main routine -- may throw
1239 int SquidMain(int argc
, char **argv
);
1240 /// unsafe main routine wrapper to catch exceptions
1241 static int SquidMainSafe(int argc
, char **argv
);
1243 #if USE_WIN32_SERVICE
1244 /* Entry point for Windows services */
1245 extern "C" void WINAPI
1246 SquidWinSvcMain(int argc
, char **argv
)
1248 SquidMainSafe(argc
, argv
);
1253 main(int argc
, char **argv
)
1255 #if USE_WIN32_SERVICE
1256 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
1257 if ((argc
== 2) && strstr(argv
[1], _WIN_SQUID_SERVICE_OPTION
))
1258 return WIN32_StartService(argc
, argv
);
1260 WIN32_run_mode
= _WIN_SQUID_RUN_MODE_INTERACTIVE
;
1265 return SquidMainSafe(argc
, argv
);
1269 SquidMainSafe(int argc
, char **argv
)
1271 (void)std::set_terminate(&OnTerminate
);
1272 // XXX: This top-level catch works great for startup, but, during runtime,
1273 // it erases valuable stack info. TODO: Let stack-preserving OnTerminate()
1274 // handle FATAL runtime errors by splitting main code into protected
1275 // startup, unprotected runtime, and protected termination sections!
1277 return SquidMain(argc
, argv
);
1279 debugs(1, DBG_CRITICAL
, "FATAL: " << CurrentException
);
1281 return EXIT_FAILURE
;
1284 /// computes name and ID for the current kid process
1286 ConfigureCurrentKid(const CommandLine
&cmdLine
)
1288 const char *kidParams
= nullptr;
1289 if (cmdLine
.hasOption(optKid
, &kidParams
)) {
1290 SBuf
processName(kidParams
);
1292 Parser::Tokenizer
tok(processName
);
1293 tok
.suffix(kidId
, CharacterSet::DIGIT
);
1294 KidIdentifier
= xatoi(kidId
.c_str());
1295 tok
.skipSuffix(SBuf("-"));
1296 TheKidName
= tok
.remaining();
1297 if (TheKidName
.cmp("squid-coord") == 0)
1298 TheProcessKind
= pkCoordinator
;
1299 else if (TheKidName
.cmp("squid") == 0)
1300 TheProcessKind
= pkWorker
;
1301 else if (TheKidName
.cmp("squid-disk") == 0)
1302 TheProcessKind
= pkDisker
;
1304 TheProcessKind
= pkOther
; // including coordinator
1306 TheKidName
.assign(APP_SHORTNAME
);
1309 Debug::NameThisKid(KidIdentifier
);
1312 /// Start directing debugs() messages to the configured cache.log.
1314 ConfigureDebugging()
1316 if (opt_no_daemon
) {
1317 fd_open(0, FD_LOG
, "stdin");
1318 fd_open(1, FD_LOG
, "stdout");
1319 fd_open(2, FD_LOG
, "stderr");
1321 // we should not create cache.log outside chroot environment, if any
1322 // XXX: With Config.chroot_dir set, SMP master process calls Debug::BanCacheLogUse().
1323 if (!Config
.chroot_dir
|| Chrooted
)
1324 Debug::UseCacheLog();
1326 Debug::BanCacheLogUse();
1332 RunRegisteredHere(RegisteredRunner::claimMemoryNeeds
);
1333 RunRegisteredHere(RegisteredRunner::useConfig
);
1341 const auto skipCwdAdjusting
= IamMasterProcess() && InDaemonMode();
1342 if (skipCwdAdjusting
) {
1343 ConfigureDebugging();
1345 } else if (Config
.chroot_dir
) {
1348 // TODO: don't we need to RunConfigUsers() in the configured
1349 // chroot environment?
1352 ConfigureDebugging();
1354 ConfigureDebugging();
1357 // TODO: since RunConfigUsers() may use a relative path, we
1358 // need to change the process root first
1364 /// register all known modules for handling future RegisteredRunner events
1368 // These registration calls do not represent a RegisteredRunner "event". The
1369 // modules registered here should be initialized later, during those events.
1371 // RegisteredRunner event handlers should not depend on handler call order
1372 // and, hence, should not depend on the registration call order below.
1374 CallRunnerRegistrator(CarpRr
);
1375 CallRunnerRegistrator(ClientDbRr
);
1376 CallRunnerRegistrator(CollapsedForwardingRr
);
1377 CallRunnerRegistrator(MemStoreRr
);
1378 CallRunnerRegistrator(PeerPoolMgrsRr
);
1379 CallRunnerRegistrator(PeerSourceHashRr
);
1380 CallRunnerRegistrator(SharedMemPagesRr
);
1381 CallRunnerRegistrator(SharedSessionCacheRr
);
1382 CallRunnerRegistrator(TransientsRr
);
1383 CallRunnerRegistratorIn(Dns
, ConfigRr
);
1385 #if HAVE_DISKIO_MODULE_IPCIO
1386 CallRunnerRegistrator(IpcIoRr
);
1389 #if HAVE_AUTH_MODULE_NTLM
1390 CallRunnerRegistrator(NtlmAuthRr
);
1394 CallRunnerRegistrator(PeerUserHashRr
);
1397 CallRunnerRegistrator(HtcpRr
);
1400 CallRunnerRegistrator(sslBumpCfgRr
);
1404 CallRunnerRegistratorIn(Rock
, SwapDirRr
);
1408 CallRunnerRegistrator(SnmpRr
);
1412 CallRunnerRegistrator(WccpRr
);
1415 CallRunnerRegistrator(Wccp2Rr
);
1420 SquidMain(int argc
, char **argv
)
1422 // We must register all modules before the first RunRegisteredHere() call.
1423 // We do it ASAP/here so that we do not need to move this code when we add
1424 // earlier hooks to the RegisteredRunner API.
1427 const CommandLine
cmdLine(argc
, argv
, shortOpStr
, squidOptions
);
1429 ConfigureCurrentKid(cmdLine
);
1431 #if defined(SQUID_MAXFD_LIMIT)
1433 if (SQUID_MAXFD_LIMIT
< Squid_MaxFD
)
1434 Squid_MaxFD
= SQUID_MAXFD_LIMIT
;
1438 /* NOP under non-windows */
1439 int WIN32_init_err
=0;
1440 if ((WIN32_init_err
= WIN32_Subsystem_Init(&argc
, &argv
)))
1441 return WIN32_init_err
;
1443 /* call mallopt() before anything else */
1446 /* Round up all sizes to a multiple of this */
1447 mallopt(M_GRAIN
, 16);
1451 /* biggest size that is considered a small block */
1452 mallopt(M_MXFAST
, 256);
1456 /* allocate this many small blocks at once */
1457 mallopt(M_NLBLKS
, 32);
1460 #endif /* HAVE_MALLOPT */
1464 squid_start
= current_time
;
1466 failure_notify
= fatal_dump
;
1468 #if USE_WIN32_SERVICE
1470 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
1473 AnyP::UriScheme::Init(); // needs to be before arg parsing, bug 5337
1475 cmdLine
.forEachOption(mainHandleCommandLineOption
);
1477 Debug::SettleStderr();
1478 Debug::SettleSyslog();
1480 if (opt_foreground
&& opt_no_daemon
) {
1481 debugs(1, DBG_CRITICAL
, "WARNING: --foreground command-line option has no effect with -N.");
1484 #if USE_WIN32_SERVICE
1486 if (opt_install_service
) {
1487 WIN32_InstallService();
1491 if (opt_remove_service
) {
1492 WIN32_RemoveService();
1496 if (opt_command_line
) {
1497 WIN32_SetServiceCommandLine();
1503 /* parse configuration file
1504 * note: in "normal" case this used to be called from mainInitialize() */
1507 ConfigFile
= xstrdup(DEFAULT_CONFIG_FILE
);
1509 assert(!configured_once
);
1513 storeFsInit(); /* required for config parsing */
1517 /* May not be needed for parsing, have not audited for such */
1518 DiskIOModule::SetupAllModules();
1520 /* we may want the parsing process to set this up in the future */
1522 Auth::Init(); /* required for config parsing. NOP if !USE_AUTH */
1523 Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing.
1525 Format::Token::Init(); // XXX: temporary. Use a runners registry of pre-parse runners instead.
1527 RunRegisteredHere(RegisteredRunner::bootstrapConfig
);
1530 Configuration::Parse();
1532 auto msg
= ConfigurationFailureMessage();
1533 if (opt_parse_cfg_only
) {
1534 debugs(3, DBG_CRITICAL
, "FATAL: " << msg
);
1535 return EXIT_FAILURE
;
1538 return EXIT_FAILURE
; // unreachable
1542 if (opt_parse_cfg_only
)
1543 return EXIT_SUCCESS
;
1545 setUmask(Config
.umask
);
1547 // Master optimization: Where possible, avoid pointless daemon fork() and/or
1548 // pointless wait for the exclusive PID file lock. This optional/weak check
1549 // is not applicable to kids because they always co-exist with their master.
1550 if (opt_send_signal
== -1 && IamMasterProcess())
1551 Instance::ThrowIfAlreadyRunning();
1553 /* send signal to running copy and exit */
1554 if (opt_send_signal
!= -1) {
1555 /* chroot if configured to run inside chroot */
1557 if (Config
.chroot_dir
) {
1567 debugs(1,2, "Doing post-config initialization");
1569 RunRegisteredHere(RegisteredRunner::finalizeConfig
);
1571 if (IamMasterProcess()) {
1572 if (InDaemonMode()) {
1573 watch_child(cmdLine
);
1576 Instance::WriteOurPid();
1583 if (opt_create_swap_dirs
) {
1585 debugs(0, DBG_CRITICAL
, "Creating missing swap directories");
1586 Store::Root().create();
1591 if (IamPrimaryProcess())
1595 /* init comm module */
1598 #if USE_WIN32_SERVICE
1600 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
1606 #if USE_WIN32_SERVICE
1608 WIN32_svcstatusupdate(SERVICE_RUNNING
, 0);
1615 SignalEngine signalEngine
;
1617 mainLoop
.registerEngine(&signalEngine
);
1619 /* TODO: stop requiring the singleton here */
1620 mainLoop
.registerEngine(EventScheduler::GetInstance());
1622 StoreRootEngine store_engine
;
1624 mainLoop
.registerEngine(&store_engine
);
1626 CommSelectEngine comm_engine
;
1628 mainLoop
.registerEngine(&comm_engine
);
1630 mainLoop
.setPrimaryEngine(&comm_engine
);
1632 /* use the standard time service */
1633 Time::Engine time_engine
;
1635 mainLoop
.setTimeService(&time_engine
);
1637 if (IamCoordinatorProcess())
1638 AsyncJob::Start(Ipc::Coordinator::Instance());
1639 else if (UsingSmp() && (IamWorkerProcess() || IamDiskProcess()))
1640 AsyncJob::Start(new Ipc::Strand
);
1642 /* at this point we are finished the synchronous startup. */
1647 if (mainLoop
.errcount
== 10)
1648 fatal_dump("Event loop exited with failure.");
1650 /* shutdown squid now */
1660 #if USE_WIN32_SERVICE
1661 // WIN32_sendSignal() does not need the PID value to signal,
1662 // but we must exit if there is no valid PID (TODO: Why?).
1663 (void)Instance::Other();
1664 if (!opt_signal_service
)
1665 throw TexcHere("missing -n command line switch");
1666 WIN32_sendSignal(opt_send_signal
);
1668 const auto pid
= Instance::Other();
1669 if (kill(pid
, opt_send_signal
) &&
1670 /* ignore permissions if just running check */
1671 !(opt_send_signal
== 0 && errno
== EPERM
)) {
1672 const auto savedErrno
= errno
;
1673 throw TexcHere(ToSBuf("failed to send signal ", opt_send_signal
,
1674 " to Squid instance with PID ", pid
, ": ", xstrerr(savedErrno
)));
1677 /* signal successfully sent */
1680 #if !_SQUID_WINDOWS_
1682 * This function is run when Squid is in daemon mode, just
1683 * before the parent forks and starts up the child process.
1684 * It can be used for admin-specific tasks, such as notifying
1685 * someone that Squid is (re)started.
1688 mainStartScript(const char *prog
)
1690 char script
[MAXPATHLEN
];
1695 xstrncpy(script
, prog
, MAXPATHLEN
);
1697 if ((t
= strrchr(script
, '/'))) {
1699 sl
= strlen(script
);
1702 xstrncpy(&script
[sl
], squid_start_script
, MAXPATHLEN
- sl
);
1704 if ((cpid
= fork()) == 0) {
1706 execl(script
, squid_start_script
, (char *)nullptr);
1711 rpid
= WaitForOnePid(cpid
, status
, 0);
1712 } while (rpid
!= cpid
);
1716 /// Initiates shutdown sequence. Shutdown ends when the last running kids stops.
1718 masterShutdownStart()
1720 if (AvoidSignalAction("shutdown", do_shutdown
))
1722 debugs(1, 2, "received shutdown command");
1726 /// Initiates reconfiguration sequence. See also: masterReconfigureFinish().
1728 masterReconfigureStart()
1730 if (AvoidSignalAction("reconfiguration", do_reconfigure
))
1732 debugs(1, 2, "received reconfiguration command");
1734 TheKids
.forgetAllFailures();
1735 // TODO: hot-reconfiguration of the number of kids, kids revival delay,
1736 // PID file location, etc.
1739 /// Ends reconfiguration sequence started by masterReconfigureStart().
1741 masterReconfigureFinish()
1746 /// Reacts to the kid revival alarm.
1750 if (AvoidSignalAction("kids revival", do_revive_kids
))
1752 debugs(1, 2, "woke up after ~" << Config
.hopelessKidRevivalDelay
<< "s");
1753 // nothing to do here -- actual revival happens elsewhere in the main loop
1754 // the alarm was needed just to wake us up so that we do a loop iteration
1758 masterCheckAndBroadcastSignals()
1761 masterShutdownStart();
1763 masterReconfigureStart();
1767 // emulate multi-step reconfiguration assumed by AvoidSignalAction()
1769 masterReconfigureFinish();
1771 BroadcastSignalIfAny(DebugSignal
);
1772 BroadcastSignalIfAny(RotateSignal
);
1773 BroadcastSignalIfAny(ReconfigureSignal
);
1774 BroadcastSignalIfAny(ShutdownSignal
);
1775 ReviveKidsSignal
= -1; // alarms are not broadcasted
1778 /// Maintains the following invariant: An alarm should be scheduled when and
1779 /// only when there are hopeless kid(s) that cannot be immediately revived.
1781 masterMaintainKidRevivalSchedule()
1783 const auto nextCheckDelay
= TheKids
.forgetOldFailures();
1784 assert(nextCheckDelay
>= 0);
1785 (void)alarm(static_cast<unsigned int>(nextCheckDelay
)); // resets or cancels
1787 debugs(1, 2, "will recheck hopeless kids in " << nextCheckDelay
<< " seconds");
1793 return (DebugSignal
> 0 || RotateSignal
> 0 || ReconfigureSignal
> 0 ||
1794 ShutdownSignal
> 0 || ReviveKidsSignal
> 0);
1797 /// makes the caller a daemon process running in the background
1802 if ((pid
= fork()) < 0) {
1804 throw TexcHere(ToSBuf("failed to fork(2) the master process: ", xstrerr(xerrno
)));
1805 } else if (pid
> 0) {
1807 // The fork() effectively duped any saved debugs() messages. For
1808 // simplicity sake, let the child process deal with them.
1809 Debug::ForgetSaved();
1812 // child, running as a background daemon
1813 Must(setsid() > 0); // ought to succeed after fork()
1819 if (TheKids
.someSignaled(SIGINT
) || TheKids
.someSignaled(SIGTERM
)) {
1820 syslog(LOG_ALERT
, "Exiting due to unexpected forced shutdown");
1824 if (TheKids
.allHopeless()) {
1825 syslog(LOG_ALERT
, "Exiting due to repeated, frequent failures");
1832 #endif /* !_SQUID_WINDOWS_ */
1835 watch_child(const CommandLine
&masterCommand
)
1837 #if !_SQUID_WINDOWS_
1843 // TODO: zero values are not supported because they result in
1844 // misconfigured SMP Squid instances running forever, endlessly
1845 // restarting each dying kid.
1846 if (Config
.hopelessKidRevivalDelay
<= 0)
1847 throw TexcHere("hopeless_kid_revival_delay must be positive");
1851 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1853 if (!opt_foreground
)
1860 if ((const auto i
= xopen("/dev/tty", O_RDWR
| O_TEXT
)) >= 0) {
1861 ioctl(i
, TIOCNOTTY
, nullptr);
1868 * RBCOLLINS - if cygwin stackdumps when squid is run without
1869 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1870 * 1.1.3. execvp had a bit overflow error in a loop..
1872 /* Connect stdio to /dev/null in daemon mode */
1873 const auto nullfd
= xopen(_PATH_DEVNULL
, O_RDWR
| O_TEXT
);
1877 fatalf(_PATH_DEVNULL
" %s\n", xstrerr(xerrno
));
1882 if (!Debug::StderrEnabled()) {
1888 Instance::WriteOurPid();
1892 #if defined(_SQUID_LINUX_THREADS_)
1893 squid_signal(SIGQUIT
, rotate_logs
, 0);
1894 squid_signal(SIGTRAP
, sigusr2_handle
, 0);
1896 squid_signal(SIGUSR1
, rotate_logs
, 0);
1897 squid_signal(SIGUSR2
, sigusr2_handle
, 0);
1900 squid_signal(SIGHUP
, reconfigure
, 0);
1902 squid_signal(SIGTERM
, master_shutdown
, 0);
1903 squid_signal(SIGALRM
, master_revive_kids
, 0);
1904 squid_signal(SIGINT
, master_shutdown
, 0);
1906 squid_signal(SIGTTIN
, master_shutdown
, 0);
1909 if (Config
.workers
> 128) {
1910 syslog(LOG_ALERT
, "Suspiciously high workers value: %d",
1912 // but we keep going in hope that user knows best
1916 configured_once
= 1;
1918 syslog(LOG_NOTICE
, "Squid Parent: will start %d kids", (int)TheKids
.count());
1920 // keep [re]starting kids until it is time to quit
1922 bool mainStartScriptCalled
= false;
1923 // start each kid that needs to be [re]started; once
1924 for (int i
= TheKids
.count() - 1; i
>= 0 && !shutting_down
; --i
) {
1925 Kid
& kid
= TheKids
.get(i
);
1926 if (!kid
.shouldRestart())
1929 if (!mainStartScriptCalled
) {
1930 mainStartScript(masterCommand
.arg0());
1931 mainStartScriptCalled
= true;
1934 // These are only needed by the forked child below, but let's keep
1935 // them out of that "no man's land" between fork() and execvp().
1936 auto kidCommand
= masterCommand
;
1937 kidCommand
.resetArg0(kid
.processName().c_str());
1938 assert(!kidCommand
.hasOption(optKid
));
1939 kidCommand
.pushFrontOption("--kid", kid
.gist().c_str());
1941 if ((pid
= fork()) == 0) {
1943 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1944 (void)execvp(masterCommand
.arg0(), kidCommand
.argv());
1946 syslog(LOG_ALERT
, "execvp failed: %s", xstrerr(xerrno
));
1950 syslog(LOG_NOTICE
, "Squid Parent: %s process %d started",
1951 kid
.processName().c_str(), pid
);
1955 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1957 // If Squid received a signal while checking for dying kids (below) or
1958 // starting new kids (above), then do a fast check for a new dying kid
1959 // (WaitForAnyPid with the WNOHANG option) and continue to forward
1960 // signals to kids. Otherwise, wait for a kid to die or for a signal
1961 // to abort the blocking WaitForAnyPid() call.
1962 // With the WNOHANG option, we could check whether WaitForAnyPid() was
1963 // aborted by a dying kid or a signal, but it is not required: The
1964 // next do/while loop will check again for any dying kids.
1966 if (masterSignaled())
1969 pid
= WaitForAnyPid(status
, waitFlag
);
1972 // check for a stopped kid
1973 if (Kid
*kid
= pid
> 0 ? TheKids
.find(pid
) : nullptr)
1976 syslog(LOG_NOTICE
, "Squid Parent: unknown child process %d exited", pid
);
1978 masterCheckAndBroadcastSignals();
1979 masterMaintainKidRevivalSchedule();
1981 if (!TheKids
.someRunning() && !TheKids
.shouldRestartSome()) {
1983 // XXX: Master process has no main loop and, hence, should not call
1984 // RegisteredRunner::startShutdown which promises a loop iteration.
1985 RunRegisteredHere(RegisteredRunner::finishShutdown
);
1992 #endif /* _SQUID_WINDOWS_ */
1999 /* XXX: This function is called after the main loop has quit, which
2000 * means that no AsyncCalls would be called, including close handlers.
2001 * TODO: We need to close/shut/free everything that needs calls before
2005 #if USE_WIN32_SERVICE
2006 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
2009 debugs(1, Important(9), "Shutting down...");
2011 Ssl::Helper::Shutdown();
2014 Ssl::CertValidationHelper::Shutdown();
2017 externalAclShutdown();
2019 releaseServerSockets();
2020 commCloseAllSockets();
2023 DelayPools::FreePools();
2026 authenticateReset();
2028 #if USE_WIN32_SERVICE
2030 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
2033 Adaptation::Icap::TheConfig
.freeService();
2036 Store::Root().sync(); /* Flush pending object writes/unlinks */
2038 unlinkdClose(); /* after sync/flush. NOP if !USE_UNLINKD */
2040 storeDirWriteCleanLogs(0);
2043 Store::Root().sync(); /* Flush log writes */
2046 Store::Root().sync(); /* Flush log close */
2047 DiskIOModule::FreeAllModules();
2053 RunRegisteredHere(RegisteredRunner::finishShutdown
);
2057 debugs(1, Important(10), "Squid Cache (Version " << version_string
<< "): Exiting normally.");
2059 exit(shutdown_status
);