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"
15 #include "acl/forward.h"
16 #include "anyp/UriScheme.h"
17 #include "auth/Config.h"
18 #include "auth/Gadgets.h"
20 #include "base/RunnersRegistry.h"
21 #include "base/Subscription.h"
22 #include "base/TextException.h"
24 #include "CachePeer.h"
25 #include "client_db.h"
26 #include "client_side.h"
28 #include "CommandLine.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"
46 #include "http/Stream.h"
47 #include "HttpHeader.h"
48 #include "HttpReply.h"
49 #include "icmp/IcmpSquid.h"
50 #include "icmp/net_db.h"
54 #include "ipc/Coordinator.h"
56 #include "ipc/Strand.h"
59 #include "neighbors.h"
60 #include "parser/Tokenizer.h"
63 #include "PeerSelectState.h"
67 #include "sbuf/Stream.h"
68 #include "SBufStatsAction.h"
69 #include "SquidConfig.h"
71 #include "StatCounters.h"
73 #include "store/Disks.h"
74 #include "store_log.h"
75 #include "StoreFileSystem.h"
76 #include "time/Engine.h"
79 #include "windows_service.h"
82 #include "adaptation/Config.h"
85 #include "adaptation/ecap/Config.h"
88 #include "adaptation/icap/Config.h"
89 #include "adaptation/icap/icap_log.h"
92 #include "ClientDelayConfig.h"
95 #include "DelayPools.h"
97 #if USE_LOADABLE_MODULES
98 #include "LoadableModules.h"
101 #include "ssl/context_storage.h"
102 #include "ssl/helper.h"
105 #include "adaptation/icap/Config.h"
108 #include "adaptation/ecap/Config.h"
111 #include "adaptation/Config.h"
114 #include "snmp_core.h"
125 #include <sys/wait.h>
128 #if USE_WIN32_SERVICE
131 static int opt_install_service
= FALSE
;
132 static int opt_remove_service
= FALSE
;
133 static int opt_command_line
= FALSE
;
134 void WIN32_svcstatusupdate(DWORD
, DWORD
);
135 void WINAPI
WIN32_svcHandler(DWORD
);
138 static int opt_signal_service
= FALSE
;
139 static char *opt_syslog_facility
= nullptr;
140 static int icpPortNumOverride
= 1; /* Want to detect "-u 0" */
141 static int configured_once
= 0;
143 static int malloc_debug_level
= 0;
145 static volatile int do_reconfigure
= 0;
146 static volatile int do_rotate
= 0;
147 static volatile int do_shutdown
= 0;
148 static volatile int do_revive_kids
= 0;
149 static volatile int shutdown_status
= EXIT_SUCCESS
;
150 static volatile int do_handle_stopped_child
= 0;
152 static int RotateSignal
= -1;
153 static int ReconfigureSignal
= -1;
154 static int ShutdownSignal
= -1;
155 static int ReviveKidsSignal
= -1;
157 static void mainRotate(void);
158 static void mainReconfigureStart(void);
159 static void mainReconfigureFinish(void*);
160 static void mainInitialize(void);
161 static void usage(void);
162 static void mainHandleCommandLineOption(const int optId
, const char *optValue
);
163 static void sendSignal(void);
164 static void serverConnectionsOpen(void);
165 static void serverConnectionsClose(void);
166 static void watch_child(const CommandLine
&);
167 static void setEffectiveUser(void);
168 static void SquidShutdown(void);
169 static void mainSetCwd(void);
172 static const char *squid_start_script
= "squid_start";
176 #include "test_access.c"
179 /** temporary thunk across to the unrefactored store interface */
181 class StoreRootEngine
: public AsyncEngine
185 int checkEvents(int) override
{
186 Store::Root().callback();
191 class SignalEngine
: public AsyncEngine
195 int checkEvents(int timeout
) override
;
198 static void StopEventLoop(void *) {
199 if (EventLoop::Running
)
200 EventLoop::Running
->stop();
203 static void FinalShutdownRunners(void *) {
204 RunRegisteredHere(RegisteredRunner::endingShutdown
);
206 // XXX: this should be a Runner.
208 /* detach the auth components (only do this on full shutdown) */
209 Auth::Scheme::FreeAll();
212 eventAdd("SquidTerminate", &StopEventLoop
, nullptr, 0, 1, false);
215 void doShutdown(time_t wait
);
216 void handleStoppedChild();
220 SignalEngine::checkEvents(int)
223 mainReconfigureStart();
226 else if (do_shutdown
)
227 doShutdown(do_shutdown
> 0 ? (int) Config
.shutdownLifetime
: 0);
228 if (do_handle_stopped_child
)
229 handleStoppedChild();
233 /// Decides whether the signal-controlled action X should be delayed, canceled,
234 /// or executed immediately. Clears do_X (via signalVar) as needed.
236 AvoidSignalAction(const char *description
, volatile int &signalVar
)
238 const char *avoiding
= "delaying";
239 const char *currentEvent
= "none";
241 currentEvent
= "shutdown";
242 avoiding
= "canceling";
243 // do not avoid repeated shutdown signals
244 // which just means the user wants to skip/abort shutdown timeouts
245 if (strcmp(currentEvent
, description
) == 0)
249 else if (!configured_once
)
250 currentEvent
= "startup";
251 else if (reconfiguring
)
252 currentEvent
= "reconfiguration";
255 return false; // do not avoid (i.e., execute immediately)
256 // the caller may produce a signal-specific debugging message
259 debugs(1, DBG_IMPORTANT
, avoiding
<< ' ' << description
<<
260 " request during " << currentEvent
);
265 SignalEngine::doShutdown(time_t wait
)
267 if (AvoidSignalAction("shutdown", do_shutdown
))
270 debugs(1, Important(2), "Preparing for shutdown after " << statCounter
.client_http
.requests
<< " requests");
271 debugs(1, Important(3), "Waiting " << wait
<< " seconds for active connections to finish");
274 // Already a shutdown signal has received and shutdown is in progress.
275 // Shutdown as soon as possible.
280 /* run the closure code which can be shared with reconfigure */
281 serverConnectionsClose();
283 RunRegisteredHere(RegisteredRunner::startShutdown
);
286 #if USE_WIN32_SERVICE
287 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, (wait
+ 1) * 1000);
290 eventAdd("SquidShutdown", &FinalShutdownRunners
, this, (double) (wait
+ 1), 1, false);
294 SignalEngine::handleStoppedChild()
296 // no AvoidSignalAction() call: This code can run at any time because it
297 // does not depend on Squid state. It does not need debugging because it
298 // handles an "internal" signal, not an external/admin command.
299 do_handle_stopped_child
= 0;
305 pid
= WaitForAnyPid(status
, WNOHANG
);
314 while (pid
> 0 || (pid
< 0 && errno
== EINTR
));
323 "Usage: %s [-cdzCFNRVYX] [-n name] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]"
324 #if USE_WIN32_SERVICE
325 "[-ir] [-O CommandLine]"
328 " -h | --help Print help message.\n"
329 " -v | --version Print version details.\n"
331 " -a port Specify HTTP port number (default: %d).\n"
332 " -d level Write debugging to stderr also.\n"
333 " -f file Use given config-file instead of\n"
335 #if USE_WIN32_SERVICE
336 " -i Installs as a Windows Service (see -n option).\n"
338 " -k reconfigure|rotate|shutdown|"
342 "interrupt|kill|debug|check|parse\n"
343 " Parse configuration file, then send signal to \n"
344 " running copy (except -k parse) and exit.\n"
345 " -n name Specify service name to use for service operations\n"
346 " default is: " APP_SHORTNAME
".\n"
347 #if USE_WIN32_SERVICE
348 " -r Removes a Windows Service (see -n option).\n"
350 " -s | -l facility\n"
351 " Enable logging to syslog.\n"
352 " -u port Specify ICP port number (default: %d), disable with 0.\n"
353 " -z Create missing swap directories and then exit.\n"
354 " -C Do not catch fatal signals.\n"
355 " -D OBSOLETE. Scheduled for removal.\n"
356 " -F Don't serve any requests until store is rebuilt.\n"
357 " -N Master process runs in foreground and is a worker. No kids.\n"
359 " Master process runs in foreground and creates worker kids.\n"
361 " Play a given SMP kid process role, with a given ID. Do not use\n"
362 " this option. It is meant for the master process use only.\n"
363 #if USE_WIN32_SERVICE
365 " Set Windows Service Command line options in Registry.\n"
367 " -R Do not set REUSEADDR on port.\n"
368 " -S Double-check swap during rebuild.\n"
369 " -X Force full debugging.\n"
370 " Add -d9 to also write full debugging to stderr.\n"
371 " -Y Only return UDP_HIT or UDP_MISS_NOFETCH during fast reload.\n",
372 APP_SHORTNAME
, CACHE_HTTP_PORT
, DEFAULT_CONFIG_FILE
, CACHE_ICP_PORT
);
376 /// CommandLine option IDs for --long options that lack a short (-x) equivalent
378 // The absolute values do not matter except that the following values should
379 // not be used: Values below 2 are for special getopt_long(3) use cases, and
380 // values in the [33,126] range are reserved for short options (-x).
386 // TODO: consider prefixing with ':' for better logging
387 // (distinguish missing required argument cases)
388 static const char *shortOpStr
=
389 #if USE_WIN32_SERVICE
392 "CDFNRSYXa:d:f:hk:m::n:sl:u:vz?";
395 static struct option squidOptions
[] = {
396 {"foreground", no_argument
, nullptr, optForeground
},
397 {"kid", required_argument
, nullptr, optKid
},
398 {"help", no_argument
, nullptr, 'h'},
399 {"version", no_argument
, nullptr, 'v'},
400 {nullptr, 0, nullptr, 0}
403 // handle a command line parameter
405 mainHandleCommandLineOption(const int optId
, const char *optValue
)
411 * Unset/disabel global option for catchign signals. opt_catch_signals */
412 opt_catch_signals
= 0;
417 * OBSOLETE: WAS: override to prevent optional startup DNS tests. */
418 debugs(1,DBG_CRITICAL
, "WARNING: -D command-line option is obsolete.");
423 * Set global option for foreground rebuild. opt_foreground_rebuild */
424 opt_foreground_rebuild
= 1;
429 * Set global option for 'no_daemon' mode. opt_no_daemon */
433 #if USE_WIN32_SERVICE
437 * Set global option. opt_command_lin and WIN32_Command_Line */
438 opt_command_line
= 1;
439 WIN32_Command_Line
= xstrdup(optValue
);
445 * Unset/disable global option opt_reuseaddr */
451 * Set global option opt_store_doublecheck */
452 opt_store_doublecheck
= 1;
457 * Force full debugging */
458 Debug::parseOptions("rotate=0 ALL,9");
459 Debug::override_X
= 1;
460 sigusr2_handle(SIGUSR2
);
465 * Set global option opt_reload_hit_only */
466 opt_reload_hit_only
= 1;
469 #if USE_WIN32_SERVICE
473 * Set global option opt_install_service (to TRUE) */
474 opt_install_service
= TRUE
;
481 * Add optional HTTP port as given following the option */
482 char *port
= xstrdup(optValue
);
483 // use a copy to avoid optValue modification
491 * debugs() messages with the given debugging level (and the more
492 * important ones) should be written to stderr */
493 Debug::ResetStderrLevel(xatoi(optValue
));
498 * Load the file given instead of the default squid.conf. */
500 ConfigFile
= xstrdup(optValue
);
505 * Run the administrative action given following the option */
507 /** \li When it is missing or an unknown option display the usage help. */
508 if (!optValue
|| strlen(optValue
) < 1)
511 else if (!strncmp(optValue
, "reconfigure", strlen(optValue
)))
512 /** \li On reconfigure send SIGHUP. */
513 opt_send_signal
= SIGHUP
;
514 else if (!strncmp(optValue
, "rotate", strlen(optValue
)))
515 /** \li On rotate send SIGQUIT or SIGUSR1. */
516 #if defined(_SQUID_LINUX_THREADS_)
517 opt_send_signal
= SIGQUIT
;
519 opt_send_signal
= SIGUSR1
;
522 else if (!strncmp(optValue
, "debug", strlen(optValue
)))
523 /** \li On debug send SIGTRAP or SIGUSR2. */
524 #if defined(_SQUID_LINUX_THREADS_)
525 opt_send_signal
= SIGTRAP
;
527 opt_send_signal
= SIGUSR2
;
530 else if (!strncmp(optValue
, "shutdown", strlen(optValue
)))
531 /** \li On shutdown send SIGTERM. */
532 opt_send_signal
= SIGTERM
;
533 else if (!strncmp(optValue
, "interrupt", strlen(optValue
)))
534 /** \li On interrupt send SIGINT. */
535 opt_send_signal
= SIGINT
;
536 else if (!strncmp(optValue
, "kill", strlen(optValue
)))
537 // XXX: In SMP mode, uncatchable SIGKILL only kills the master process
538 /** \li On kill send SIGKILL. */
539 opt_send_signal
= SIGKILL
;
543 else if (!strncmp(optValue
, "restart", strlen(optValue
)))
544 /** \li On restart send SIGTTIN. (exit and restart by parent) */
545 opt_send_signal
= SIGTTIN
;
549 else if (!strncmp(optValue
, "check", strlen(optValue
)))
550 /** \li On check send 0 / SIGNULL. */
551 opt_send_signal
= 0; /* SIGNULL */
552 else if (!strncmp(optValue
, "parse", strlen(optValue
)))
553 /** \li On parse set global flag to re-parse the config file only. */
554 opt_parse_cfg_only
= 1;
558 // Cannot use cache.log: use stderr for important messages (by default)
559 // and stop expecting a Debug::UseCacheLog() call.
560 Debug::EnsureDefaultStderrLevel(DBG_IMPORTANT
);
561 Debug::BanCacheLogUse();
566 * Set global malloc_debug_level to the value given following the option.
567 * if none is given it toggles the xmalloc_trace option on/off */
570 malloc_debug_level
= xatoi(optValue
);
572 fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
580 * Set global option opt_signal_service (to true).
581 * Stores the additional parameter given in global service_name */
582 if (optValue
&& *optValue
!= '\0') {
583 const SBuf
t(optValue
);
584 ::Parser::Tokenizer
tok(t
);
585 const CharacterSet chr
= CharacterSet::ALPHA
+CharacterSet::DIGIT
;
586 if (!tok
.prefix(service_name
, chr
))
587 fatalf("Expected alphanumeric service name for the -n option but got: %s", optValue
);
589 fatalf("Garbage after alphanumeric service name in the -n option value: %s", optValue
);
590 if (service_name
.length() > 32)
591 fatalf("Service name (-n option) must be limited to 32 characters but got %u", service_name
.length());
592 opt_signal_service
= true;
594 fatal("A service name is required for the -n option");
598 #if USE_WIN32_SERVICE
602 * Set global option opt_remove_service (to TRUE) */
603 opt_remove_service
= TRUE
;
611 * Stores the syslog facility name in global opt_syslog_facility
612 * then performs actions for -s option. */
613 xfree(opt_syslog_facility
); // ignore any previous options sent
614 opt_syslog_facility
= xstrdup(optValue
);
615 Debug::ConfigureSyslog(opt_syslog_facility
);
620 * Initialize the syslog for output */
621 Debug::ConfigureSyslog(opt_syslog_facility
);
626 * Store the ICP port number given in global option icpPortNumOverride
627 * ensuring its a positive number. */
628 icpPortNumOverride
= atoi(optValue
);
630 if (icpPortNumOverride
< 0)
631 icpPortNumOverride
= 0;
637 * Display squid version and build information. Then exit. */
638 printf("Squid Cache: Version %s\n",version_string
);
639 printf("Service Name: " SQUIDSBUFPH
"\n", SQUIDSBUFPRINT(service_name
));
640 if (strlen(SQUID_BUILD_INFO
))
641 printf("%s\n",SQUID_BUILD_INFO
);
643 printf("\nThis binary uses %s. ", OpenSSL_version(OPENSSL_VERSION
));
644 #if OPENSSL_VERSION_MAJOR < 3
645 printf("For legal restrictions on distribution see https://www.openssl.org/source/license.html\n\n");
648 printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS
);
650 #if USE_WIN32_SERVICE
652 printf("Compiled as Windows System Service.\n");
662 * Request cache_dir initialization */
663 opt_create_swap_dirs
= 1;
664 // We will use cache.log, but this command is often executed on the
665 // command line, so use stderr to show important messages (by default).
666 // TODO: Generalize/fix this -z-specific and sometimes faulty logic with
667 // "use stderr when it is a tty [until we GoIntoBackground()]" logic.
668 Debug::EnsureDefaultStderrLevel(DBG_IMPORTANT
);
672 /** \par --foreground
673 * Set global option opt_foreground */
678 // already processed in ConfigureCurrentKid()
686 /** \par h,?, or unknown
687 * \copydoc usage() */
703 signal(sig
, rotate_logs
);
713 ReconfigureSignal
= sig
;
717 signal(sig
, reconfigure
);
723 master_revive_kids(int sig
)
725 ReviveKidsSignal
= sig
;
726 do_revive_kids
= true;
730 signal(sig
, master_revive_kids
);
735 /// Shutdown signal handler for master process
737 master_shutdown(int sig
)
740 ShutdownSignal
= sig
;
744 signal(sig
, master_shutdown
);
753 do_shutdown
= sig
== SIGINT
? -1 : 1;
754 ShutdownSignal
= sig
;
757 shutdown_status
= EXIT_FAILURE
;
760 #if !defined(_SQUID_WINDOWS_) && !defined(HAVE_SIGACTION)
761 signal(sig
, shut_down
);
768 do_handle_stopped_child
= 1;
770 #if !defined(_SQUID_WINDOWS_) && !defined(HAVE_SIGACTION)
771 signal(sig
, sig_child
);
778 serverConnectionsOpen(void)
780 // start various proxying services if we are responsible for them
781 if (IamWorkerProcess()) {
782 clientOpenListenSockets();
794 Acl::Node::Initialize();
800 serverConnectionsClose(void)
802 assert(shutting_down
|| reconfiguring
);
804 if (IamWorkerProcess()) {
805 clientConnectionsClose();
806 icpConnectionShutdown();
808 htcpSocketShutdown();
821 mainReconfigureStart(void)
823 if (AvoidSignalAction("reconfiguration", do_reconfigure
))
826 debugs(1, DBG_IMPORTANT
, "Reconfiguring Squid Cache (version " << version_string
<< ")...");
829 RunRegisteredHere(RegisteredRunner::startReconfigure
);
831 // Initiate asynchronous closing sequence
832 serverConnectionsClose();
838 Ssl::TheGlobalContextStorage().reconfigureStart();
843 externalAclShutdown();
844 storeDirCloseSwapLogs();
850 Security::CloseLogs();
852 eventAdd("mainReconfigureFinish", &mainReconfigureFinish
, nullptr, 0, 1,
856 /// error message to log when Configuration::Parse() fails
858 ConfigurationFailureMessage()
861 out
<< (reconfiguring
? "re" : "");
862 out
<< "configuration failure: " << CurrentException
;
863 if (!opt_parse_cfg_only
)
864 out
<< Debug::Extra
<< "advice: Run 'squid -k parse' and check for ERRORs.";
869 mainReconfigureFinish(void *)
871 debugs(1, 3, "finishing reconfiguring");
874 enter_suid(); /* root to read config file */
876 // we may have disabled the need for PURGE
877 if (Config2
.onoff
.enable_purge
)
878 Config2
.onoff
.enable_purge
= 2;
880 const int oldWorkers
= Config
.workers
;
883 Configuration::Parse();
885 // for now any errors are a fatal condition...
886 fatal(ConfigurationFailureMessage().c_str());
889 if (oldWorkers
!= Config
.workers
) {
890 debugs(1, DBG_CRITICAL
, "WARNING: Changing 'workers' (from " <<
891 oldWorkers
<< " to " << Config
.workers
<<
892 ") requires a full restart. It has been ignored by reconfigure.");
893 Config
.workers
= oldWorkers
;
896 RunRegisteredHere(RegisteredRunner::syncConfig
);
898 if (IamPrimaryProcess())
900 CpuAffinityReconfigure();
902 setUmask(Config
.umask
);
904 Debug::UseCacheLog();
905 ipcache_restart(); /* clear stuck entries */
906 fqdncache_restart(); /* sigh, fqdncache too */
908 errorInitialize(); /* reload error pages */
911 #if USE_LOADABLE_MODULES
912 LoadableModulesConfigure(Config
.loadable_module_names
);
916 bool enableAdaptation
= false;
918 Adaptation::Icap::TheConfig
.finalize();
919 enableAdaptation
= Adaptation::Icap::TheConfig
.onoff
|| enableAdaptation
;
922 Adaptation::Ecap::TheConfig
.finalize(); // must be after we load modules
923 enableAdaptation
= Adaptation::Ecap::TheConfig
.onoff
|| enableAdaptation
;
925 Adaptation::Config::Finalize(enableAdaptation
);
928 Security::OpenLogs();
935 Ssl::Helper::Reconfigure();
938 Ssl::CertValidationHelper::Reconfigure();
941 redirectReconfigure();
943 authenticateInit(&Auth::TheConfig
.schemes
);
947 serverConnectionsOpen();
951 storeDirOpenSwapLogs();
953 mimeInit(Config
.mimeTablePathname
);
959 Config
.ClientDelay
.finalize();
968 if (AvoidSignalAction("log rotation", do_rotate
))
974 authenticateRotate();
976 externalAclShutdown();
978 _db_rotate_log(); /* cache.log */
979 storeDirWriteCleanLogs(1);
980 storeLogRotate(); /* store.log */
981 accessLogRotate(); /* access.log */
982 Security::RotateLogs();
984 icapLogRotate(); /*icap.log*/
989 authenticateInit(&Auth::TheConfig
.schemes
);
995 setEffectiveUser(void)
998 leave_suid(); /* Run as non privilegied user */
1004 if (geteuid() == 0) {
1005 debugs(0, DBG_CRITICAL
, "Squid is not safe to run as root! If you must");
1006 debugs(0, DBG_CRITICAL
, "start Squid as root, then you must configure");
1007 debugs(0, DBG_CRITICAL
, "it to run as a non-priveledged user with the");
1008 debugs(0, DBG_CRITICAL
, "'cache_effective_user' option in the config file.");
1009 fatal("Don't run Squid as root, set 'cache_effective_user'!");
1013 /// changes working directory, providing error reporting
1015 mainChangeDir(const char *dir
)
1017 if (chdir(dir
) == 0)
1021 debugs(50, DBG_CRITICAL
, "ERROR: cannot change current directory to " << dir
<<
1022 ": " << xstrerr(xerrno
));
1026 /// Hack: Have we called chroot()? This exposure is needed because some code has
1027 /// to open the same files before and after chroot()
1028 bool Chrooted
= false;
1030 /// set the working directory.
1034 if (Config
.chroot_dir
&& !Chrooted
) {
1037 if (chroot(Config
.chroot_dir
) != 0) {
1039 fatalf("chroot to %s failed: %s", Config
.chroot_dir
, xstrerr(xerrno
));
1042 if (!mainChangeDir("/"))
1043 fatalf("chdir to / after chroot to %s failed", Config
.chroot_dir
);
1046 if (Config
.coredump_dir
&& strcmp("none", Config
.coredump_dir
) != 0) {
1047 if (mainChangeDir(Config
.coredump_dir
)) {
1048 debugs(0, Important(4), "Set Current Directory to " << Config
.coredump_dir
);
1053 /* If we don't have coredump_dir or couldn't cd there, report current dir */
1054 char pathbuf
[MAXPATHLEN
];
1055 if (getcwd(pathbuf
, MAXPATHLEN
)) {
1056 debugs(0, DBG_IMPORTANT
, "Current Directory is " << pathbuf
);
1059 debugs(50, DBG_CRITICAL
, "WARNING: Can't find current directory, getcwd: " << xstrerr(xerrno
));
1064 mainInitialize(void)
1066 if (opt_catch_signals
) {
1067 squid_signal(SIGSEGV
, death
, SA_NODEFER
| SA_RESETHAND
);
1068 squid_signal(SIGBUS
, death
, SA_NODEFER
| SA_RESETHAND
);
1071 squid_signal(SIGPIPE
, SIG_IGN
, SA_RESTART
);
1072 squid_signal(SIGCHLD
, sig_child
, SA_NODEFER
| SA_RESTART
);
1073 squid_signal(SIGHUP
, reconfigure
, SA_RESTART
);
1077 if (icpPortNumOverride
!= 1)
1078 Config
.Port
.icp
= (unsigned short) icpPortNumOverride
;
1080 debugs(1, DBG_CRITICAL
, "Starting Squid Cache version " << version_string
<< " for " << CONFIG_HOST_TYPE
<< "...");
1081 debugs(1, Critical(5), "Service Name: " << service_name
);
1084 if (WIN32_run_mode
== _WIN_SQUID_RUN_MODE_SERVICE
) {
1085 debugs(1, DBG_CRITICAL
, "Service command line is: " << WIN32_Service_Command_Line
);
1087 debugs(1, DBG_CRITICAL
, "Running on " << WIN32_OS_string
);
1090 debugs(1, Important(6), "Process ID " << getpid());
1092 debugs(1, Important(7), "Process Roles:" << ProcessRoles());
1095 debugs(1, Important(8), "With " << Squid_MaxFD
<< " file descriptors available");
1099 debugs(1, DBG_IMPORTANT
, "With " << _getmaxstdio() << " CRT stdio descriptors available");
1101 if (WIN32_Socks_initialized
)
1102 debugs(1, DBG_IMPORTANT
, "Windows sockets initialized");
1104 if (WIN32_OS_version
> _WIN_OS_WINNT
) {
1105 WIN32_IpAddrChangeMonitorInit();
1119 Ssl::Helper::Init();
1123 Ssl::CertValidationHelper::Init();
1128 authenticateInit(&Auth::TheConfig
.schemes
);
1132 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
1138 Security::OpenLogs();
1151 malloc_debug(0, malloc_debug_level
);
1155 if (unlinkdNeeded())
1162 mimeInit(Config
.mimeTablePathname
);
1168 FwdState::initModule();
1169 SBufStatsAction::RegisterWithCacheManager();
1171 AsyncJob::RegisterWithCacheManager();
1173 /* These use separate calls so that the comm loops can eventually
1179 // TODO: pconn is a good candidate for new-style registration
1180 // PconnModule::GetInstance()->registerWithCacheManager();
1181 // moved to PconnModule::PconnModule()
1183 serverConnectionsOpen();
1187 // neighborsRegisterWithCacheManager(); //moved to neighbors_init()
1189 if (Config
.chroot_dir
)
1192 #if defined(_SQUID_LINUX_THREADS_)
1194 squid_signal(SIGQUIT
, rotate_logs
, SA_RESTART
);
1196 squid_signal(SIGTRAP
, sigusr2_handle
, SA_RESTART
);
1200 squid_signal(SIGUSR1
, rotate_logs
, SA_RESTART
);
1202 squid_signal(SIGUSR2
, sigusr2_handle
, SA_RESTART
);
1206 squid_signal(SIGTERM
, shut_down
, SA_RESTART
);
1208 squid_signal(SIGINT
, shut_down
, SA_RESTART
);
1212 squid_signal(SIGTTIN
, shut_down
, SA_RESTART
);
1216 #if USE_LOADABLE_MODULES
1217 LoadableModulesConfigure(Config
.loadable_module_names
);
1221 bool enableAdaptation
= false;
1223 // We can remove this dependency on specific adaptation mechanisms
1224 // if we create a generic Registry of such mechanisms. Should we?
1226 Adaptation::Icap::TheConfig
.finalize();
1227 enableAdaptation
= Adaptation::Icap::TheConfig
.onoff
|| enableAdaptation
;
1230 Adaptation::Ecap::TheConfig
.finalize(); // must be after we load modules
1231 enableAdaptation
= Adaptation::Ecap::TheConfig
.onoff
|| enableAdaptation
;
1233 // must be the last adaptation-related finalize
1234 Adaptation::Config::Finalize(enableAdaptation
);
1238 Config
.ClientDelay
.finalize();
1241 eventAdd("storeMaintain", Store::Maintain
, nullptr, 1.0, 1);
1243 eventAdd("ipcache_purgelru", ipcache_purgelru
, nullptr, 10.0, 1);
1245 eventAdd("fqdncache_purgelru", fqdncache_purgelru
, nullptr, 15.0, 1);
1247 eventAdd("memPoolCleanIdlePools", Mem::CleanIdlePools
, nullptr, 15.0, 1);
1249 configured_once
= 1;
1255 // ignore recursive calls to avoid termination loops
1256 static bool terminating
= false;
1261 debugs(1, DBG_CRITICAL
, "FATAL: Dying after an undetermined failure" << CurrentExceptionExtra
);
1263 Debug::PrepareToDie();
1267 /// unsafe main routine -- may throw
1268 int SquidMain(int argc
, char **argv
);
1269 /// unsafe main routine wrapper to catch exceptions
1270 static int SquidMainSafe(int argc
, char **argv
);
1272 #if USE_WIN32_SERVICE
1273 /* Entry point for Windows services */
1274 extern "C" void WINAPI
1275 SquidWinSvcMain(int argc
, char **argv
)
1277 SquidMainSafe(argc
, argv
);
1282 main(int argc
, char **argv
)
1284 #if USE_WIN32_SERVICE
1285 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
1286 if ((argc
== 2) && strstr(argv
[1], _WIN_SQUID_SERVICE_OPTION
))
1287 return WIN32_StartService(argc
, argv
);
1289 WIN32_run_mode
= _WIN_SQUID_RUN_MODE_INTERACTIVE
;
1294 return SquidMainSafe(argc
, argv
);
1298 SquidMainSafe(int argc
, char **argv
)
1300 (void)std::set_terminate(&OnTerminate
);
1301 // XXX: This top-level catch works great for startup, but, during runtime,
1302 // it erases valuable stack info. TODO: Let stack-preserving OnTerminate()
1303 // handle FATAL runtime errors by splitting main code into protected
1304 // startup, unprotected runtime, and protected termination sections!
1306 return SquidMain(argc
, argv
);
1308 debugs(1, DBG_CRITICAL
, "FATAL: " << CurrentException
);
1310 return EXIT_FAILURE
;
1313 /// computes name and ID for the current kid process
1315 ConfigureCurrentKid(const CommandLine
&cmdLine
)
1317 const char *kidParams
= nullptr;
1318 if (cmdLine
.hasOption(optKid
, &kidParams
)) {
1319 SBuf
processName(kidParams
);
1321 Parser::Tokenizer
tok(processName
);
1322 tok
.suffix(kidId
, CharacterSet::DIGIT
);
1323 KidIdentifier
= xatoi(kidId
.c_str());
1324 tok
.skipSuffix(SBuf("-"));
1325 TheKidName
= tok
.remaining();
1326 if (TheKidName
.cmp("squid-coord") == 0)
1327 TheProcessKind
= pkCoordinator
;
1328 else if (TheKidName
.cmp("squid") == 0)
1329 TheProcessKind
= pkWorker
;
1330 else if (TheKidName
.cmp("squid-disk") == 0)
1331 TheProcessKind
= pkDisker
;
1333 TheProcessKind
= pkOther
; // including coordinator
1335 TheKidName
.assign(APP_SHORTNAME
);
1338 Debug::NameThisKid(KidIdentifier
);
1341 /// Start directing debugs() messages to the configured cache.log.
1343 ConfigureDebugging()
1345 if (opt_no_daemon
) {
1346 fd_open(0, FD_LOG
, "stdin");
1347 fd_open(1, FD_LOG
, "stdout");
1348 fd_open(2, FD_LOG
, "stderr");
1350 // we should not create cache.log outside chroot environment, if any
1351 // XXX: With Config.chroot_dir set, SMP master process calls Debug::BanCacheLogUse().
1352 if (!Config
.chroot_dir
|| Chrooted
)
1353 Debug::UseCacheLog();
1355 Debug::BanCacheLogUse();
1361 RunRegisteredHere(RegisteredRunner::claimMemoryNeeds
);
1362 RunRegisteredHere(RegisteredRunner::useConfig
);
1370 const auto skipCwdAdjusting
= IamMasterProcess() && InDaemonMode();
1371 if (skipCwdAdjusting
) {
1372 ConfigureDebugging();
1374 } else if (Config
.chroot_dir
) {
1377 // TODO: don't we need to RunConfigUsers() in the configured
1378 // chroot environment?
1381 ConfigureDebugging();
1383 ConfigureDebugging();
1386 // TODO: since RunConfigUsers() may use a relative path, we
1387 // need to change the process root first
1393 /// register all known modules for handling future RegisteredRunner events
1397 // These registration calls do not represent a RegisteredRunner "event". The
1398 // modules registered here should be initialized later, during those events.
1400 // RegisteredRunner event handlers should not depend on handler call order
1401 // and, hence, should not depend on the registration call order below.
1403 CallRunnerRegistrator(CarpRr
);
1404 CallRunnerRegistrator(ClientDbRr
);
1405 CallRunnerRegistrator(CollapsedForwardingRr
);
1406 CallRunnerRegistrator(MemStoreRr
);
1407 CallRunnerRegistrator(PeerPoolMgrsRr
);
1408 CallRunnerRegistrator(PeerSourceHashRr
);
1409 CallRunnerRegistrator(SharedMemPagesRr
);
1410 CallRunnerRegistrator(SharedSessionCacheRr
);
1411 CallRunnerRegistrator(TransientsRr
);
1412 CallRunnerRegistratorIn(Dns
, ConfigRr
);
1414 #if HAVE_DISKIO_MODULE_IPCIO
1415 CallRunnerRegistrator(IpcIoRr
);
1418 #if HAVE_AUTH_MODULE_NTLM
1419 CallRunnerRegistrator(NtlmAuthRr
);
1423 CallRunnerRegistrator(PeerUserHashRr
);
1427 CallRunnerRegistrator(sslBumpCfgRr
);
1431 CallRunnerRegistratorIn(Rock
, SwapDirRr
);
1435 CallRunnerRegistrator(WccpRr
);
1438 CallRunnerRegistrator(Wccp2Rr
);
1443 SquidMain(int argc
, char **argv
)
1445 // We must register all modules before the first RunRegisteredHere() call.
1446 // We do it ASAP/here so that we do not need to move this code when we add
1447 // earlier hooks to the RegisteredRunner API.
1450 const CommandLine
cmdLine(argc
, argv
, shortOpStr
, squidOptions
);
1452 ConfigureCurrentKid(cmdLine
);
1454 #if defined(SQUID_MAXFD_LIMIT)
1456 if (SQUID_MAXFD_LIMIT
< Squid_MaxFD
)
1457 Squid_MaxFD
= SQUID_MAXFD_LIMIT
;
1461 /* NOP under non-windows */
1462 int WIN32_init_err
=0;
1463 if ((WIN32_init_err
= WIN32_Subsystem_Init(&argc
, &argv
)))
1464 return WIN32_init_err
;
1466 /* call mallopt() before anything else */
1469 /* Round up all sizes to a multiple of this */
1470 mallopt(M_GRAIN
, 16);
1474 /* biggest size that is considered a small block */
1475 mallopt(M_MXFAST
, 256);
1479 /* allocate this many small blocks at once */
1480 mallopt(M_NLBLKS
, 32);
1483 #endif /* HAVE_MALLOPT */
1487 squid_start
= current_time
;
1489 failure_notify
= fatal_dump
;
1491 #if USE_WIN32_SERVICE
1493 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
1496 AnyP::UriScheme::Init(); // needs to be before arg parsing, bug 5337
1498 cmdLine
.forEachOption(mainHandleCommandLineOption
);
1500 Debug::SettleStderr();
1501 Debug::SettleSyslog();
1503 if (opt_foreground
&& opt_no_daemon
) {
1504 debugs(1, DBG_CRITICAL
, "WARNING: --foreground command-line option has no effect with -N.");
1507 #if USE_WIN32_SERVICE
1509 if (opt_install_service
) {
1510 WIN32_InstallService();
1514 if (opt_remove_service
) {
1515 WIN32_RemoveService();
1519 if (opt_command_line
) {
1520 WIN32_SetServiceCommandLine();
1526 /* parse configuration file
1527 * note: in "normal" case this used to be called from mainInitialize() */
1530 ConfigFile
= xstrdup(DEFAULT_CONFIG_FILE
);
1532 assert(!configured_once
);
1536 storeFsInit(); /* required for config parsing */
1540 /* May not be needed for parsing, have not audited for such */
1541 DiskIOModule::SetupAllModules();
1543 /* we may want the parsing process to set this up in the future */
1545 Auth::Init(); /* required for config parsing. NOP if !USE_AUTH */
1546 Ip::ProbeTransport(); // determine IPv4 or IPv6 capabilities before parsing.
1548 Format::Token::Init(); // XXX: temporary. Use a runners registry of pre-parse runners instead.
1550 RunRegisteredHere(RegisteredRunner::bootstrapConfig
);
1553 Configuration::Parse();
1555 auto msg
= ConfigurationFailureMessage();
1556 if (opt_parse_cfg_only
) {
1557 debugs(3, DBG_CRITICAL
, "FATAL: " << msg
);
1558 return EXIT_FAILURE
;
1561 return EXIT_FAILURE
; // unreachable
1565 if (opt_parse_cfg_only
)
1566 return EXIT_SUCCESS
;
1568 setUmask(Config
.umask
);
1570 // Master optimization: Where possible, avoid pointless daemon fork() and/or
1571 // pointless wait for the exclusive PID file lock. This optional/weak check
1572 // is not applicable to kids because they always co-exist with their master.
1573 if (opt_send_signal
== -1 && IamMasterProcess())
1574 Instance::ThrowIfAlreadyRunning();
1576 /* send signal to running copy and exit */
1577 if (opt_send_signal
!= -1) {
1578 /* chroot if configured to run inside chroot */
1580 if (Config
.chroot_dir
) {
1590 debugs(1,2, "Doing post-config initialization");
1592 RunRegisteredHere(RegisteredRunner::finalizeConfig
);
1594 if (IamMasterProcess()) {
1595 if (InDaemonMode()) {
1596 watch_child(cmdLine
);
1599 Instance::WriteOurPid();
1606 if (opt_create_swap_dirs
) {
1608 debugs(0, DBG_CRITICAL
, "Creating missing swap directories");
1609 Store::Root().create();
1614 if (IamPrimaryProcess())
1618 /* init comm module */
1621 #if USE_WIN32_SERVICE
1623 WIN32_svcstatusupdate(SERVICE_START_PENDING
, 10000);
1629 #if USE_WIN32_SERVICE
1631 WIN32_svcstatusupdate(SERVICE_RUNNING
, 0);
1638 SignalEngine signalEngine
;
1640 mainLoop
.registerEngine(&signalEngine
);
1642 /* TODO: stop requiring the singleton here */
1643 mainLoop
.registerEngine(EventScheduler::GetInstance());
1645 StoreRootEngine store_engine
;
1647 mainLoop
.registerEngine(&store_engine
);
1649 CommSelectEngine comm_engine
;
1651 mainLoop
.registerEngine(&comm_engine
);
1653 mainLoop
.setPrimaryEngine(&comm_engine
);
1655 /* use the standard time service */
1656 Time::Engine time_engine
;
1658 mainLoop
.setTimeService(&time_engine
);
1660 if (IamCoordinatorProcess())
1661 AsyncJob::Start(Ipc::Coordinator::Instance());
1662 else if (UsingSmp() && (IamWorkerProcess() || IamDiskProcess()))
1663 AsyncJob::Start(new Ipc::Strand
);
1665 /* at this point we are finished the synchronous startup. */
1670 if (mainLoop
.errcount
== 10)
1671 fatal_dump("Event loop exited with failure.");
1673 /* shutdown squid now */
1683 #if USE_WIN32_SERVICE
1684 // WIN32_sendSignal() does not need the PID value to signal,
1685 // but we must exit if there is no valid PID (TODO: Why?).
1686 (void)Instance::Other();
1687 if (!opt_signal_service
)
1688 throw TexcHere("missing -n command line switch");
1689 WIN32_sendSignal(opt_send_signal
);
1691 const auto pid
= Instance::Other();
1692 if (kill(pid
, opt_send_signal
) &&
1693 /* ignore permissions if just running check */
1694 !(opt_send_signal
== 0 && errno
== EPERM
)) {
1695 const auto savedErrno
= errno
;
1696 throw TexcHere(ToSBuf("failed to send signal ", opt_send_signal
,
1697 " to Squid instance with PID ", pid
, ": ", xstrerr(savedErrno
)));
1700 /* signal successfully sent */
1703 #if !_SQUID_WINDOWS_
1705 * This function is run when Squid is in daemon mode, just
1706 * before the parent forks and starts up the child process.
1707 * It can be used for admin-specific tasks, such as notifying
1708 * someone that Squid is (re)started.
1711 mainStartScript(const char *prog
)
1713 char script
[MAXPATHLEN
];
1718 xstrncpy(script
, prog
, MAXPATHLEN
);
1720 if ((t
= strrchr(script
, '/'))) {
1722 sl
= strlen(script
);
1725 xstrncpy(&script
[sl
], squid_start_script
, MAXPATHLEN
- sl
);
1727 if ((cpid
= fork()) == 0) {
1729 execl(script
, squid_start_script
, (char *)nullptr);
1734 rpid
= WaitForOnePid(cpid
, status
, 0);
1735 } while (rpid
!= cpid
);
1739 /// Initiates shutdown sequence. Shutdown ends when the last running kids stops.
1741 masterShutdownStart()
1743 if (AvoidSignalAction("shutdown", do_shutdown
))
1745 debugs(1, 2, "received shutdown command");
1749 /// Initiates reconfiguration sequence. See also: masterReconfigureFinish().
1751 masterReconfigureStart()
1753 if (AvoidSignalAction("reconfiguration", do_reconfigure
))
1755 debugs(1, 2, "received reconfiguration command");
1757 TheKids
.forgetAllFailures();
1758 // TODO: hot-reconfiguration of the number of kids, kids revival delay,
1759 // PID file location, etc.
1762 /// Ends reconfiguration sequence started by masterReconfigureStart().
1764 masterReconfigureFinish()
1769 /// Reacts to the kid revival alarm.
1773 if (AvoidSignalAction("kids revival", do_revive_kids
))
1775 debugs(1, 2, "woke up after ~" << Config
.hopelessKidRevivalDelay
<< "s");
1776 // nothing to do here -- actual revival happens elsewhere in the main loop
1777 // the alarm was needed just to wake us up so that we do a loop iteration
1781 masterCheckAndBroadcastSignals()
1784 masterShutdownStart();
1786 masterReconfigureStart();
1790 // emulate multi-step reconfiguration assumed by AvoidSignalAction()
1792 masterReconfigureFinish();
1794 BroadcastSignalIfAny(DebugSignal
);
1795 BroadcastSignalIfAny(RotateSignal
);
1796 BroadcastSignalIfAny(ReconfigureSignal
);
1797 BroadcastSignalIfAny(ShutdownSignal
);
1798 ReviveKidsSignal
= -1; // alarms are not broadcasted
1801 /// Maintains the following invariant: An alarm should be scheduled when and
1802 /// only when there are hopeless kid(s) that cannot be immediately revived.
1804 masterMaintainKidRevivalSchedule()
1806 const auto nextCheckDelay
= TheKids
.forgetOldFailures();
1807 assert(nextCheckDelay
>= 0);
1808 (void)alarm(static_cast<unsigned int>(nextCheckDelay
)); // resets or cancels
1810 debugs(1, 2, "will recheck hopeless kids in " << nextCheckDelay
<< " seconds");
1816 return (DebugSignal
> 0 || RotateSignal
> 0 || ReconfigureSignal
> 0 ||
1817 ShutdownSignal
> 0 || ReviveKidsSignal
> 0);
1820 /// makes the caller a daemon process running in the background
1825 if ((pid
= fork()) < 0) {
1827 throw TexcHere(ToSBuf("failed to fork(2) the master process: ", xstrerr(xerrno
)));
1828 } else if (pid
> 0) {
1830 // The fork() effectively duped any saved debugs() messages. For
1831 // simplicity sake, let the child process deal with them.
1832 Debug::ForgetSaved();
1835 // child, running as a background daemon
1836 Must(setsid() > 0); // ought to succeed after fork()
1842 if (TheKids
.someSignaled(SIGINT
) || TheKids
.someSignaled(SIGTERM
)) {
1843 syslog(LOG_ALERT
, "Exiting due to unexpected forced shutdown");
1847 if (TheKids
.allHopeless()) {
1848 syslog(LOG_ALERT
, "Exiting due to repeated, frequent failures");
1855 #endif /* !_SQUID_WINDOWS_ */
1858 watch_child(const CommandLine
&masterCommand
)
1860 #if !_SQUID_WINDOWS_
1869 // TODO: zero values are not supported because they result in
1870 // misconfigured SMP Squid instances running forever, endlessly
1871 // restarting each dying kid.
1872 if (Config
.hopelessKidRevivalDelay
<= 0)
1873 throw TexcHere("hopeless_kid_revival_delay must be positive");
1877 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1879 if (!opt_foreground
)
1886 if ((i
= open("/dev/tty", O_RDWR
| O_TEXT
)) >= 0) {
1887 ioctl(i
, TIOCNOTTY
, nullptr);
1894 * RBCOLLINS - if cygwin stackdumps when squid is run without
1895 * -N, check the cygwin1.dll version, it needs to be AT LEAST
1896 * 1.1.3. execvp had a bit overflow error in a loop..
1898 /* Connect stdio to /dev/null in daemon mode */
1899 nullfd
= open(_PATH_DEVNULL
, O_RDWR
| O_TEXT
);
1903 fatalf(_PATH_DEVNULL
" %s\n", xstrerr(xerrno
));
1908 if (!Debug::StderrEnabled()) {
1914 Instance::WriteOurPid();
1918 #if defined(_SQUID_LINUX_THREADS_)
1919 squid_signal(SIGQUIT
, rotate_logs
, 0);
1920 squid_signal(SIGTRAP
, sigusr2_handle
, 0);
1922 squid_signal(SIGUSR1
, rotate_logs
, 0);
1923 squid_signal(SIGUSR2
, sigusr2_handle
, 0);
1926 squid_signal(SIGHUP
, reconfigure
, 0);
1928 squid_signal(SIGTERM
, master_shutdown
, 0);
1929 squid_signal(SIGALRM
, master_revive_kids
, 0);
1930 squid_signal(SIGINT
, master_shutdown
, 0);
1932 squid_signal(SIGTTIN
, master_shutdown
, 0);
1935 if (Config
.workers
> 128) {
1936 syslog(LOG_ALERT
, "Suspiciously high workers value: %d",
1938 // but we keep going in hope that user knows best
1942 configured_once
= 1;
1944 syslog(LOG_NOTICE
, "Squid Parent: will start %d kids", (int)TheKids
.count());
1946 // keep [re]starting kids until it is time to quit
1948 bool mainStartScriptCalled
= false;
1949 // start each kid that needs to be [re]started; once
1950 for (int i
= TheKids
.count() - 1; i
>= 0 && !shutting_down
; --i
) {
1951 Kid
& kid
= TheKids
.get(i
);
1952 if (!kid
.shouldRestart())
1955 if (!mainStartScriptCalled
) {
1956 mainStartScript(masterCommand
.arg0());
1957 mainStartScriptCalled
= true;
1960 // These are only needed by the forked child below, but let's keep
1961 // them out of that "no man's land" between fork() and execvp().
1962 auto kidCommand
= masterCommand
;
1963 kidCommand
.resetArg0(kid
.processName().c_str());
1964 assert(!kidCommand
.hasOption(optKid
));
1965 kidCommand
.pushFrontOption("--kid", kid
.gist().c_str());
1967 if ((pid
= fork()) == 0) {
1969 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1970 (void)execvp(masterCommand
.arg0(), kidCommand
.argv());
1972 syslog(LOG_ALERT
, "execvp failed: %s", xstrerr(xerrno
));
1976 syslog(LOG_NOTICE
, "Squid Parent: %s process %d started",
1977 kid
.processName().c_str(), pid
);
1981 openlog(APP_SHORTNAME
, LOG_PID
| LOG_NDELAY
| LOG_CONS
, LOG_LOCAL4
);
1983 // If Squid received a signal while checking for dying kids (below) or
1984 // starting new kids (above), then do a fast check for a new dying kid
1985 // (WaitForAnyPid with the WNOHANG option) and continue to forward
1986 // signals to kids. Otherwise, wait for a kid to die or for a signal
1987 // to abort the blocking WaitForAnyPid() call.
1988 // With the WNOHANG option, we could check whether WaitForAnyPid() was
1989 // aborted by a dying kid or a signal, but it is not required: The
1990 // next do/while loop will check again for any dying kids.
1992 if (masterSignaled())
1995 pid
= WaitForAnyPid(status
, waitFlag
);
1998 // check for a stopped kid
1999 if (Kid
*kid
= pid
> 0 ? TheKids
.find(pid
) : nullptr)
2002 syslog(LOG_NOTICE
, "Squid Parent: unknown child process %d exited", pid
);
2004 masterCheckAndBroadcastSignals();
2005 masterMaintainKidRevivalSchedule();
2007 if (!TheKids
.someRunning() && !TheKids
.shouldRestartSome()) {
2009 // XXX: Master process has no main loop and, hence, should not call
2010 // RegisteredRunner::startShutdown which promises a loop iteration.
2011 RunRegisteredHere(RegisteredRunner::finishShutdown
);
2018 #endif /* _SQUID_WINDOWS_ */
2025 /* XXX: This function is called after the main loop has quit, which
2026 * means that no AsyncCalls would be called, including close handlers.
2027 * TODO: We need to close/shut/free everything that needs calls before
2031 #if USE_WIN32_SERVICE
2032 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
2035 debugs(1, Important(9), "Shutting down...");
2037 Ssl::Helper::Shutdown();
2040 Ssl::CertValidationHelper::Shutdown();
2043 externalAclShutdown();
2051 releaseServerSockets();
2052 commCloseAllSockets();
2055 DelayPools::FreePools();
2058 authenticateReset();
2060 #if USE_WIN32_SERVICE
2062 WIN32_svcstatusupdate(SERVICE_STOP_PENDING
, 10000);
2065 Adaptation::Icap::TheConfig
.freeService();
2068 Store::Root().sync(); /* Flush pending object writes/unlinks */
2070 unlinkdClose(); /* after sync/flush. NOP if !USE_UNLINKD */
2072 storeDirWriteCleanLogs(0);
2075 Store::Root().sync(); /* Flush log writes */
2078 Store::Root().sync(); /* Flush log close */
2079 DiskIOModule::FreeAllModules();
2085 RunRegisteredHere(RegisteredRunner::finishShutdown
);
2089 debugs(1, Important(10), "Squid Cache (Version " << version_string
<< "): Exiting normally.");
2091 exit(shutdown_status
);