/*
- * $Id: main.cc,v 1.395 2004/12/20 14:52:27 robertc Exp $
+ * $Id: main.cc,v 1.453 2007/12/29 18:20:22 hno Exp $
*
* DEBUG: section 1 Startup and Main Loop
* AUTHOR: Harvest Derived
#include "squid.h"
#include "AccessLogEntry.h"
#include "authenticate.h"
+#include "CacheManager.h"
+#include "ConfigParser.h"
+#include "errorpage.h"
+#include "event.h"
+#include "EventLoop.h"
+#include "ExternalACL.h"
#include "Store.h"
#include "ICP.h"
#include "HttpReply.h"
+#include "pconn.h"
#include "Mem.h"
#include "ACLASN.h"
#include "ACL.h"
#include "htcp.h"
#include "StoreFileSystem.h"
+#include "DiskIO/DiskIOModule.h"
#include "comm.h"
+#if USE_EPOLL
+#include "comm_epoll.h"
+#endif
+#if USE_KQUEUE
+#include "comm_kqueue.h"
+#endif
+#if USE_POLL
+#include "comm_poll.h"
+#endif
+#if USE_SELECT
+#include "comm_select.h"
+#endif
+#if USE_SELECT_WIN32
+#include "comm_select.h"
+#endif
+#include "SquidTime.h"
+#include "SwapDir.h"
+#include "forward.h"
+#include "MemPool.h"
+#include "ICMPSquid.h"
#if USE_WIN32_SERVICE
/* for error reporting from xmalloc and friends */
SQUIDCEXTERN void (*failure_notify) (const char *);
-static int opt_send_signal = -1;
static int opt_parse_cfg_only = 0;
+static char *opt_syslog_facility = NULL;
static int icpPortNumOverride = 1; /* Want to detect "-u 0" */
static int configured_once = 0;
#if MALLOC_DBG
static volatile int do_reconfigure = 0;
static volatile int do_rotate = 0;
static volatile int do_shutdown = 0;
+static volatile int shutdown_status = 0;
static void mainRotate(void);
static void mainReconfigure(void);
extern void log_trace_done();
extern void log_trace_init(char *);
#endif
-static EVH SquidShutdown;
+static void SquidShutdown(void);
static void mainSetCwd(void);
static int checkRunningPid(void);
+static CacheManager manager;
+
#ifndef _SQUID_MSWIN_
static const char *squid_start_script = "squid_start";
#endif
#include "test_access.c"
#endif
+/* temporary thunk across to the unrefactored store interface */
+
+class StoreRootEngine : public AsyncEngine
+{
+
+public:
+ int checkEvents(int timeout)
+ {
+ Store::Root().callback();
+ return EVENT_IDLE;
+ };
+};
+
+class SignalDispatcher : public CompletionDispatcher
+{
+
+public:
+ SignalDispatcher(EventLoop &loop) : loop(loop), events_dispatched(false) {}
+
+ void addEventLoop(EventLoop * loop);
+ virtual bool dispatch();
+
+private:
+ static void StopEventLoop(void * data)
+ {
+ static_cast<SignalDispatcher *>(data)->loop.stop();
+ }
+
+ EventLoop &loop;
+ bool events_dispatched;
+};
+
+bool
+SignalDispatcher::dispatch()
+{
+ PROF_start(SignalDispatcher_dispatch);
+
+ if (do_reconfigure) {
+ mainReconfigure();
+ do_reconfigure = 0;
+ } else if (do_rotate) {
+ mainRotate();
+ do_rotate = 0;
+ } else if (do_shutdown) {
+ time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
+ debugs(1, 1, "Preparing for shutdown after " << statCounter.client_http.requests << " requests");
+ debugs(1, 1, "Waiting " << wait << " seconds for active connections to finish");
+ do_shutdown = 0;
+ shutting_down = 1;
+#if USE_WIN32_SERVICE
+
+ WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);
+#endif
+
+ serverConnectionsClose();
+ eventAdd("SquidShutdown", StopEventLoop, this, (double) (wait + 1), 1, false);
+ }
+
+ bool result = events_dispatched;
+ events_dispatched = false;
+ PROF_stop(SignalDispatcher_dispatch);
+ return result;
+}
+
static void
usage(void)
{
fprintf(stderr,
#if USE_WIN32_SERVICE
- "Usage: %s [-cdhirsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal] [-n name] [-O CommandLine]\n"
+ "Usage: %s [-cdhirvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal] [-n name] [-O CommandLine]\n"
#else
- "Usage: %s [-cdhsvzCDFNRVYX] [-f config-file] [-[au] port] [-k signal]\n"
+ "Usage: %s [-cdhvzCDFNRVYX] [-s | -l facility] [-f config-file] [-[au] port] [-k signal]\n"
#endif
" -a port Specify HTTP port number (default: %d).\n"
" -d level Write debugging to stderr also.\n"
" default is: " _WIN_SQUID_DEFAULT_SERVICE_NAME ".\n"
" -r Removes a Windows Service (see -n option).\n"
#endif
- " -s Enable logging to syslog.\n"
+ " -s | -l facility\n"
+ " Enable logging to syslog.\n"
" -u port Specify ICP port number (default: %d), disable with 0.\n"
" -v Print version.\n"
" -z Create swap directories\n"
#if USE_WIN32_SERVICE
- while ((c = getopt(argc, argv, "CDFNO:RSVYXa:d:f:hik:m::n:rsu:vz?")) != -1)
+ while ((c = getopt(argc, argv, "CDFNO:RSVYXa:d:f:hik:m::n:rsl:u:vz?")) != -1)
#else
- while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1)
+ while ((c = getopt(argc, argv, "CDFNRSYXa:d:f:hk:m::sl:u:vz?")) != -1)
#endif
{
opt_store_doublecheck = 1;
break;
- case 'V':
-
- if (Config.Sockaddr.http)
- Config.Sockaddr.http->vhost = 1;
-
-#if USE_SSL
-
- else if (Config.Sockaddr.https)
- Config.Sockaddr.https->http.vhost = 1;
-
-#endif
-
- else
- fatal("No http_port specified\n");
-
- break;
-
case 'X':
/* force full debugging */
+ Debug::parseOptions("debug_options ALL,9");
+ Config.onoff.debug_override_X = 1;
sigusr2_handle(SIGUSR2);
-
break;
case 'Y':
break;
case 'k':
+
if ((int) strlen(optarg) < 1)
usage();
opt_send_signal = SIGINT;
else if (!strncmp(optarg, "kill", strlen(optarg)))
opt_send_signal = SIGKILL;
+
+#ifdef SIGTTIN
+
+ else if (!strncmp(optarg, "restart", strlen(optarg)))
+ opt_send_signal = SIGTTIN; /* exit and restart by parent */
+
+#endif
+
else if (!strncmp(optarg, "check", strlen(optarg)))
opt_send_signal = 0; /* SIGNULL */
else if (!strncmp(optarg, "parse", strlen(optarg)))
if (optarg) {
#if MALLOC_DBG
malloc_debug_level = atoi(optarg);
- /* NOTREACHED */
- break;
#else
fatal("Need to add -DMALLOC_DBG when compiling to use -mX option");
- /* NOTREACHED */
#endif
} else {
}
+ break;
+ /* NOTREACHED */
+
#if USE_WIN32_SERVICE
case 'n':
#endif
+ case 'l':
+ opt_syslog_facility = xstrdup(optarg);
+
case 's':
#if HAVE_SYSLOG
- opt_syslog_enable = 1;
+ _db_set_syslog(opt_syslog_facility);
break;
/* NOTREACHED */
case 'z':
+ opt_debug_stderr = 1;
+
opt_create_swap_dirs = 1;
break;
shut_down(int sig)
{
do_shutdown = sig == SIGINT ? -1 : 1;
+#ifdef SIGTTIN
+
+ if (SIGTTIN == sig)
+ shutdown_status = 1;
+
+#endif
#ifndef _SQUID_MSWIN_
#ifdef KILL_PARENT_OPT
if (getppid() > 1) {
- debug(1, 1) ("Killing RunCache, pid %d\n", getppid());
+ debugs(1, 1, "Killing RunCache, pid " << getppid());
if (kill(getppid(), sig) < 0)
- debug(1, 1) ("kill %d: %s\n", getppid(), xstrerror());
+ debugs(1, 1, "kill " << getppid() << ": " << xstrerror());
}
#endif
wccpConnectionOpen();
#endif
+#if USE_WCCPv2
+
+ wccp2ConnectionOpen();
+#endif
+
clientdbInit();
- icmpOpen();
+ icmpEngine.Open();
netdbInit();
asnInit();
ACL::Initialize();
htcpSocketShutdown();
#endif
- icmpClose();
+ icmpEngine.Close();
#ifdef SQUID_SNMP
snmpConnectionShutdown();
#endif
#if USE_WCCP
- wccpConnectionShutdown();
+ wccpConnectionClose();
+#endif
+#if USE_WCCPv2
+
+ wccp2ConnectionClose();
#endif
asnFreeMemory();
static void
mainReconfigure(void)
{
- debug(1, 1) ("Reconfiguring Squid Cache (version %s)...\n", version_string);
+ debugs(1, 1, "Reconfiguring Squid Cache (version " << version_string << ")...");
reconfiguring = 1;
/* Already called serverConnectionsClose and ipcacheShutdownServers() */
serverConnectionsClose();
snmpConnectionClose();
#endif
-#if USE_WCCP
-
- wccpConnectionClose();
-#endif
#if USE_DNSSERVERS
dnsShutdown();
refererCloseLog();
errorClean();
enter_suid(); /* root to read config file */
- parseConfigFile(ConfigFile);
+ parseConfigFile(ConfigFile, manager);
setEffectiveUser();
_db_init(Config.Log.log, Config.debugOptions);
ipcache_restart(); /* clear stuck entries */
wccpInit();
#endif
+#if USE_WCCPv2
+
+ wccp2Init();
+#endif
serverConnectionsOpen();
+
neighbors_init();
+ neighborsRegisterWithCacheManager(manager);
+
storeDirOpenSwapLogs();
+
mimeInit(Config.mimeTablePathname);
+
+ if (Config.onoff.announce) {
+ if (!eventFind(start_announce, NULL))
+ eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
+ } else {
+ if (eventFind(start_announce, NULL))
+ eventDelete(start_announce, NULL);
+ }
+
writePidFile(); /* write PID file */
- debug(1, 1) ("Ready to serve requests.\n");
+
+ debugs(1, 1, "Ready to serve requests.");
+
reconfiguring = 0;
}
static void
mainRotate(void)
{
- icmpClose();
+ icmpEngine.Close();
#if USE_DNSSERVERS
dnsShutdown();
fwdLogRotate();
#endif
- icmpOpen();
+ icmpEngine.Open();
#if USE_DNSSERVERS
dnsInit();
static void
setEffectiveUser(void)
{
+ keepCapabilities();
leave_suid(); /* Run as non privilegied user */
#ifdef _SQUID_OS2_
#endif
if (geteuid() == 0) {
- debug(0, 0) ("Squid is not safe to run as root! If you must\n");
- debug(0, 0) ("start Squid as root, then you must configure\n");
- debug(0, 0) ("it to run as a non-priveledged user with the\n");
- debug(0, 0) ("'cache_effective_user' option in the config file.\n");
+ debugs(0, 0, "Squid is not safe to run as root! If you must");
+ debugs(0, 0, "start Squid as root, then you must configure");
+ debugs(0, 0, "it to run as a non-priveledged user with the");
+ debugs(0, 0, "'cache_effective_user' option in the config file.");
fatal("Don't run Squid as root, set 'cache_effective_user'!");
}
}
if (0 == strcmp("none", Config.coredump_dir)) {
(void) 0;
} else if (chdir(Config.coredump_dir) == 0) {
- debug(0, 1) ("Set Current Directory to %s\n", Config.coredump_dir);
+ debugs(0, 1, "Set Current Directory to " << Config.coredump_dir);
return;
} else {
- debug(50, 0) ("chdir: %s: %s\n", Config.coredump_dir, xstrerror());
+ debugs(50, 0, "chdir: " << Config.coredump_dir << ": " << xstrerror());
}
}
/* If we don't have coredump_dir or couldn't cd there, report current dir */
if (getcwd(pathbuf, MAXPATHLEN)) {
- debug(0, 1) ("Current Directory is %s\n", pathbuf);
+ debugs(0, 1, "Current Directory is " << pathbuf);
} else {
- debug(50, 0) ("WARNING: Can't find current directory, getcwd: %s\n", xstrerror());
+ debugs(50, 0, "WARNING: Can't find current directory, getcwd: " << xstrerror());
}
}
{
/* chroot if configured to run inside chroot */
- if (Config.chroot_dir && chroot(Config.chroot_dir)) {
+ if (Config.chroot_dir && (chroot(Config.chroot_dir) != 0 || chdir("/") != 0)) {
fatal("failed to chroot");
}
#endif
- debug(1, 0) ("Starting Squid Cache version %s for %s...\n",
- version_string,
- CONFIG_HOST_TYPE);
+ debugs(1, 0, "Starting Squid Cache version " << version_string << " for " << CONFIG_HOST_TYPE << "...");
#ifdef _SQUID_WIN32_
if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) {
- debug(1, 0) ("Running as %s Windows System Service on %s\n", WIN32_Service_name, WIN32_OS_string);
- debug(1, 0) ("Service command line is: %s\n", WIN32_Service_Command_Line);
+ debugs(1, 0, "Running as " << WIN32_Service_name << " Windows System Service on " << WIN32_OS_string);
+ debugs(1, 0, "Service command line is: " << WIN32_Service_Command_Line);
} else
- debug(1, 0) ("Running on %s\n",WIN32_OS_string);
+ debugs(1, 0, "Running on " << WIN32_OS_string);
#endif
- debug(1, 1) ("Process ID %d\n", (int) getpid());
+ debugs(1, 1, "Process ID " << getpid());
- debug(1, 1) ("With %d file descriptors available\n", Squid_MaxFD);
+ debugs(1, 1, "With " << Squid_MaxFD << " file descriptors available");
#ifdef _SQUID_MSWIN_
- debug(1, 1) ("With %d CRT stdio descriptors available\n", _getmaxstdio());
+ debugs(1, 1, "With " << _getmaxstdio() << " CRT stdio descriptors available");
if (WIN32_Socks_initialized)
- debug(1, 1)("Windows sockets initialized\n");
+ debugs(1, 1, "Windows sockets initialized");
#endif
#endif
urlInitialize();
- cachemgrInit();
statInit();
storeInit();
mainSetCwd();
/* after this point we want to see the mallinfo() output */
do_mallinfo = 1;
mimeInit(Config.mimeTablePathname);
- pconnInit();
refreshInit();
#if DELAY_POOLS
DelayPools::Init();
#endif
- fwdInit();
+ FwdState::initModule();
+ /* register the modules in the cache manager menus */
+ accessLogRegisterWithCacheManager(manager);
+ asnRegisterWithCacheManager(manager);
+ authenticateRegisterWithCacheManager(&Config.authConfiguration, manager);
+#if USE_CARP
+
+ carpRegisterWithCacheManager(manager);
+#endif
+
+ cbdataRegisterWithCacheManager(manager);
+ /* These use separate calls so that the comm loops can eventually
+ * coexist.
+ */
+#ifdef USE_EPOLL
+
+ commEPollRegisterWithCacheManager(manager);
+#endif
+#ifdef USE_KQUEUE
+
+ commKQueueRegisterWithCacheManager(manager);
+#endif
+#ifdef USE_POLL
+
+ commPollRegisterWithCacheManager(manager);
+#endif
+#ifdef USE_SELECT
+
+ commSelectRegisterWithCacheManager(manager);
+#endif
+
+ clientdbRegisterWithCacheManager(manager);
+#if DELAY_POOLS
+
+ DelayPools::RegisterWithCacheManager(manager);
+#endif
+
+ DiskIOModule::RegisterAllModulesWithCacheManager(manager);
+#if USE_DNSSERVERS
+
+ dnsRegisterWithCacheManager(manager);
+#endif
+
+ eventInit(manager);
+ externalAclRegisterWithCacheManager(manager);
+ fqdncacheRegisterWithCacheManager(manager);
+ FwdState::RegisterWithCacheManager(manager);
+ httpHeaderRegisterWithCacheManager(manager);
+#if !USE_DNSSERVERS
+
+ idnsRegisterWithCacheManager(manager);
+#endif
+
+ ipcacheRegisterWithCacheManager(manager);
+ Mem::RegisterWithCacheManager(manager);
+ netdbRegisterWitHCacheManager(manager);
+ PconnModule::GetInstance()->registerWithCacheManager(manager);
+ redirectRegisterWithCacheManager(manager);
+ refreshRegisterWithCacheManager(manager);
+ statRegisterWithCacheManager(manager);
+ storeDigestRegisterWithCacheManager(manager);
+ StoreFileSystem::RegisterAllFsWithCacheManager(manager);
+ storeRegisterWithCacheManager(manager);
+ storeLogRegisterWithCacheManager(manager);
+#if DEBUGSTRINGS
+
+ StringRegistry::Instance().registerWithCacheManager(manager);
+#endif
+
+#if USE_XPROF_STATS
+
+ xprofRegisterWithCacheManager(manager);
+#endif
+
}
#if USE_WCCP
wccpInit();
+#endif
+#if USE_WCCPv2
+
+ wccp2Init();
+
#endif
serverConnectionsOpen();
neighbors_init();
+ neighborsRegisterWithCacheManager(manager);
+
if (Config.chroot_dir)
no_suid();
squid_signal(SIGINT, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
+#ifdef SIGTTIN
+
+ squid_signal(SIGTTIN, shut_down, SA_NODEFER | SA_RESETHAND | SA_RESTART);
+
+#endif
+
memCheckInit();
- debug(1, 1) ("Ready to serve requests.\n");
+ debugs(1, 1, "Ready to serve requests.");
if (!configured_once) {
- eventAdd("storeMaintain", storeMaintainSwapSpace, NULL, 1.0, 1);
+ eventAdd("storeMaintain", Store::Maintain, NULL, 1.0, 1);
if (Config.onoff.announce)
eventAdd("start_announce", start_announce, NULL, 3600.0, 1);
#if USE_WIN32_SERVICE
/* When USE_WIN32_SERVICE is defined, the main function is placed in win32.cc */
extern "C" void WINAPI
- SquidMain(int argc, char **argv)
+ SquidWinSvcMain(int argc, char **argv)
+{
+ SquidMain(argc, argv);
+}
+
+int
+SquidMain(int argc, char **argv)
#else
int
main(int argc, char **argv)
#endif
{
- int errcount = 0;
- int n; /* # of GC'd objects */
mode_t oldmask;
+#ifdef _SQUID_WIN32_
+
+ int WIN32_init_err;
+#endif
#if HAVE_SBRK
sbrk_start = sbrk(0);
#endif
- Debug::parseOptions("ALL,1");
+ Debug::parseOptions(NULL);
debug_log = stderr;
- if (FD_SETSIZE < Squid_MaxFD)
- Squid_MaxFD = FD_SETSIZE;
+#if defined(SQUID_MAXFD_LIMIT)
-#ifdef _SQUID_WIN32_
-#ifdef USE_WIN32_SERVICE
+ if (SQUID_MAXFD_LIMIT < Squid_MaxFD)
+ Squid_MaxFD = SQUID_MAXFD_LIMIT;
- if (WIN32_Subsystem_Init(&argc, &argv))
- return;
-
-#else
+#endif
- {
- int WIN32_init_err;
+#ifdef _SQUID_WIN32_
- if ((WIN32_init_err = WIN32_Subsystem_Init()))
- return WIN32_init_err;
- }
-#endif
+ if ((WIN32_init_err = WIN32_Subsystem_Init(&argc, &argv)))
+ return WIN32_init_err;
#endif
if (oldmask)
umask(oldmask);
- memset(&local_addr, '\0', sizeof(struct in_addr));
-
- safe_inet_addr(localhost, &local_addr);
-
- memset(&any_addr, '\0', sizeof(struct in_addr));
-
- safe_inet_addr("0.0.0.0", &any_addr);
-
- memset(&no_addr, '\0', sizeof(struct in_addr));
-
- safe_inet_addr("255.255.255.255", &no_addr);
-
squid_srandom(time(NULL));
getCurrentTime();
#if USE_WIN32_SERVICE
- if (opt_install_service) {
+ if (opt_install_service)
+ {
WIN32_InstallService();
- return;
+ return 0;
}
- if (opt_remove_service) {
+ if (opt_remove_service)
+ {
WIN32_RemoveService();
- return;
+ return 0;
}
- if (opt_command_line) {
+ if (opt_command_line)
+ {
WIN32_SetServiceCommandLine();
- return;
+ return 0;
}
#endif
assert(!configured_once);
-#if USE_LEAKFINDER
-
- leakInit();
-
-#endif
-
Mem::Init();
- cbdataInit();
-
- eventInit(); /* eventInit() is required for config parsing */
-
storeFsInit(); /* required for config parsing */
+ /* May not be needed for parsing, have not audited for such */
+ DiskIOModule::SetupAllModules();
+
/* Shouldn't be needed for config parsing, but have not audited for such */
StoreFileSystem::SetupAllFs();
- parse_err = parseConfigFile(ConfigFile);
-
- if (opt_parse_cfg_only)
-#if USE_WIN32_SERVICE
+ /* we may want the parsing process to set this up in the future */
+ Store::Root(new StoreController);
- return;
+ parse_err = parseConfigFile(ConfigFile, manager);
-#else
+ if (opt_parse_cfg_only)
return parse_err;
-
-#endif
-
}
if (-1 == opt_send_signal)
if (checkRunningPid())
#endif
/* send signal to running copy and exit */
- if (opt_send_signal != -1) {
+ if (opt_send_signal != -1)
+ {
/* chroot if configured to run inside chroot */
- if (Config.chroot_dir && chroot(Config.chroot_dir)) {
- fatal("failed to chroot");
+ if (Config.chroot_dir) {
+ if (chroot(Config.chroot_dir))
+ fatal("failed to chroot");
+
+ no_suid();
+ } else {
+ leave_suid();
}
sendSignal();
/* NOTREACHED */
}
- if (opt_create_swap_dirs) {
+ if (opt_create_swap_dirs)
+ {
/* chroot if configured to run inside chroot */
if (Config.chroot_dir && chroot(Config.chroot_dir)) {
}
setEffectiveUser();
- debug(0, 0) ("Creating Swap Directories\n");
- storeCreateSwapDirectories();
-#if USE_WIN32_SERVICE
-
- return;
-#else
+ debugs(0, 0, "Creating Swap Directories");
+ Store::Root().create();
return 0;
-#endif
-
}
if (!opt_no_daemon)
setMaxFD();
- if (opt_catch_signals)
- for (n = Squid_MaxFD; n > 2; n--)
- close(n);
-
/* init comm module */
comm_init();
comm_select_init();
- if (opt_no_daemon) {
+ if (opt_no_daemon)
+ {
/* we have to init fdstat here. */
fd_open(0, FD_LOG, "stdin");
fd_open(1, FD_LOG, "stdout");
#endif
/* main loop */
+ EventLoop mainLoop;
- for (;;) {
- if (do_reconfigure) {
- mainReconfigure();
- do_reconfigure = 0;
-#if defined(_SQUID_MSWIN_) && defined(_DEBUG)
-
- } else if (do_debug) {
- do_debug = 0;
- __asm int 3;
-#endif
-
- } else if (do_rotate) {
- mainRotate();
- do_rotate = 0;
- } else if (do_shutdown) {
- time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
- debug(1, 1) ("Preparing for shutdown after %d requests\n",
- statCounter.client_http.requests);
- debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
- (int) wait);
- do_shutdown = 0;
- shutting_down = 1;
-#if USE_WIN32_SERVICE
-
- WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);
-#endif
-
- serverConnectionsClose();
- eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
- }
+ SignalDispatcher signal_dispatcher(mainLoop);
- eventRun();
- int loop_delay = eventNextTime();
+ mainLoop.registerDispatcher(&signal_dispatcher);
- if (loop_delay < 0)
- loop_delay = 0;
+ /* TODO: stop requiring the singleton here */
+ mainLoop.registerDispatcher(EventDispatcher::GetInstance());
- /* Attempt any pending storedir IO */
- storeDirCallback();
+ /* TODO: stop requiring the singleton here */
+ mainLoop.registerEngine(EventScheduler::GetInstance());
- comm_calliocallback();
+ StoreRootEngine store_engine;
- /* and again to deal with indirectly queued events
- * resulting from the first call. These are usually
- * callbacks and should be dealt with immediately.
- */
- if (comm_iocallbackpending())
- comm_calliocallback();
+ mainLoop.registerEngine(&store_engine);
- switch (comm_select(loop_delay)) {
+ CommDispatcher comm_dispatcher;
- case COMM_OK:
- errcount = 0; /* reset if successful */
- break;
+ mainLoop.registerDispatcher(&comm_dispatcher);
- case COMM_ERROR:
- errcount++;
- debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
+ CommSelectEngine comm_engine;
- if (errcount == 10)
- fatal_dump("Select Loop failed!");
+ mainLoop.registerEngine(&comm_engine);
- break;
+ mainLoop.setPrimaryEngine(&comm_engine);
- case COMM_TIMEOUT:
- break;
+ /* use the standard time service */
+ TimeEngine time_engine;
- case COMM_SHUTDOWN:
- SquidShutdown(NULL);
+ mainLoop.setTimeService(&time_engine);
- break;
+ mainLoop.run();
- default:
- fatal_dump("MAIN: Internal error -- this should never happen.");
+ if (mainLoop.errcount == 10)
+ fatal_dump("Event loop exited with failure.");
- break;
- }
- }
+ /* shutdown squid now */
+ SquidShutdown();
/* NOTREACHED */
-#if USE_WIN32_SERVICE
- return;
-
-#else
-
return 0;
-
-#endif
}
static void
debug_log = stderr;
if (strcmp(Config.pidFilename, "none") == 0) {
- debug(0, 1) ("No pid_filename specified. Trusting you know what you are doing.\n");
+ debugs(0, 1, "No pid_filename specified. Trusting you know what you are doing.");
}
pid = readPidFile();
if ((cpid = fork()) == 0) {
/* child */
- execl(script, squid_start_script, 0);
- _exit(0);
+ execl(script, squid_start_script, (char *)NULL);
+ _exit(-1);
} else {
do {
#ifdef _SQUID_NEXT_
checkRunningPid(void)
{
pid_t pid;
- debug_log = stderr;
+
+ if (!debug_log)
+ debug_log = stderr;
+
pid = readPidFile();
if (pid < 2)
#endif
pid_t pid;
+#ifdef TIOCNOTTY
+
int i;
+#endif
+
int nullfd;
if (*(argv[0]) == '(')
#endif
-
/*
* RBCOLLINS - if cygwin stackdumps when squid is run without
* -N, check the cygwin1.dll version, it needs to be AT LEAST
* 1.1.3. execvp had a bit overflow error in a loop..
*/
/* Connect stdio to /dev/null in daemon mode */
- nullfd = open("/dev/null", O_RDWR | O_TEXT);
+ nullfd = open(_PATH_DEVNULL, O_RDWR | O_TEXT);
if (nullfd < 0)
- fatalf("/dev/null: %s\n", xstrerror());
+ fatalf(_PATH_DEVNULL " %s\n", xstrerror());
dup2(nullfd, 0);
dup2(nullfd, 2);
}
- /* Close all else */
- for (i = 3; i < Squid_MaxFD; i++)
- close(i);
-
for (;;) {
mainStartScript(argv[0]);
pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
syslog(LOG_NOTICE,
- "Squid Parent: child process %d exited due to signal %d",
- pid, WTERMSIG(status));
+ "Squid Parent: child process %d exited due to signal %d with status %d",
+ pid, WTERMSIG(status), WEXITSTATUS(status));
} else {
syslog(LOG_NOTICE, "Squid Parent: child process %d exited", pid);
}
exit(0);
break;
+ case SIGINT:
+ case SIGTERM:
+ syslog(LOG_ALERT, "Exiting due to unexpected forced shutdown");
+ exit(1);
+ break;
+
default:
break;
}
/* NOTREACHED */
#endif /* _SQUID_MSWIN_ */
+
}
static void
-SquidShutdown(void *unused)
+SquidShutdown()
{
#if USE_WIN32_SERVICE
WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
#endif
- debug(1, 1) ("Shutting down...\n");
+ debugs(1, 1, "Shutting down...");
#if USE_DNSSERVERS
dnsShutdown();
wccpConnectionClose();
#endif
+#if USE_WCCPv2
+
+ wccp2ConnectionClose();
+#endif
releaseServerSockets();
commCloseAllSockets();
#endif
authenticateShutdown();
-#if USE_UNLINKD
-
- unlinkdClose();
-#endif
#if USE_WIN32_SERVICE
WIN32_svcstatusupdate(SERVICE_STOP_PENDING, 10000);
#endif
- storeDirSync(); /* Flush pending object writes/unlinks */
+ Store::Root().sync(); /* Flush pending object writes/unlinks */
+#if USE_UNLINKD
+
+ unlinkdClose(); /* after sync/flush */
+#endif
+
storeDirWriteCleanLogs(0);
PrintRusage();
dumpMallocStats();
- storeDirSync(); /* Flush log writes */
+ Store::Root().sync(); /* Flush log writes */
storeLogClose();
accessLogClose();
useragentLogClose();
fwdUninit();
#endif
- storeDirSync(); /* Flush log close */
+ Store::Root().sync(); /* Flush log close */
StoreFileSystem::FreeAllFs();
-#if PURIFY || XMALLOC_TRACE
+ DiskIOModule::FreeAllModules();
+#if LEAK_CHECK_MODE && 0 /* doesn't work at the moment */
configFreeMemory();
storeFreeMemory();
#endif
fdDumpOpen();
- fdFreeMemory();
+ comm_exit();
memClean();
xmalloc_find_leaks();
- debug(1, 0) ("Memory used after shutdown: %d\n", xmalloc_total);
+ debugs(1, 0, "Memory used after shutdown: " << xmalloc_total);
#endif
#if MEM_GEN_TRACE
leave_suid();
}
- debug(1, 1) ("Squid Cache (Version %s): Exiting normally.\n",
- version_string);
+ debugs(1, 1, "Squid Cache (Version " << version_string << "): Exiting normally.");
- if (debug_log)
- fclose(debug_log);
+ /*
+ * DPW 2006-10-23
+ * We used to fclose(debug_log) here if it was set, but then
+ * we forgot to set it to NULL. That caused some coredumps
+ * because exit() ends up calling a bunch of destructors and
+ * such. So rather than forcing the debug_log to close, we'll
+ * leave it open so that those destructors can write some
+ * debugging if necessary. The file will be closed anyway when
+ * the process truly exits.
+ */
- exit(0);
+ exit(shutdown_status);
}
+