From: Alex Rousskov Date: Mon, 26 Apr 2010 07:53:14 +0000 (-0600) Subject: Designate one process to maintain the PID file. Coordinator does that X-Git-Tag: SQUID_3_2_0_1~93^2~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a2c48c983912d7c29054d38d138bbc2f0f590411;p=thirdparty%2Fsquid.git Designate one process to maintain the PID file. Coordinator does that when Squid runs in SMP mode. The only kid does it when running "mono". The master process does it when not daemonizing. This change allows SMP Squid to work with a single PID file. Broadcast management signals from Coordinator to kids. This change makes both "squid -k ..." and "kill `cat `" work for SMP Squid. --- diff --git a/src/ipc/Coordinator.cc b/src/ipc/Coordinator.cc index b0e4893e24..6976b1c5ab 100644 --- a/src/ipc/Coordinator.cc +++ b/src/ipc/Coordinator.cc @@ -11,6 +11,7 @@ CBDATA_NAMESPACED_CLASS_INIT(Ipc, Coordinator); +Ipc::Coordinator* Ipc::Coordinator::TheInstance = NULL; Ipc::Coordinator::Coordinator(): @@ -62,3 +63,23 @@ void Ipc::Coordinator::handleRegistrationRequest(const StrandData& strand) SendMessage(MakeAddr(strandAddrPfx, strand.kidId), Message(mtRegistration, strand.kidId, strand.pid)); } + +void Ipc::Coordinator::broadcastSignal(int sig) const +{ + typedef Vector::const_iterator VSDCI; + for (VSDCI iter = strands.begin(); iter != strands.end(); ++iter) { + debugs(54, 5, HERE << "signal " << sig << " to kid" << iter->kidId << + ", PID=" << iter->pid); + kill(iter->pid, sig); + } +} + +Ipc::Coordinator* Ipc::Coordinator::Instance() +{ + if (!TheInstance) + TheInstance = new Coordinator; + // XXX: if the Coordinator job quits, this pointer will become invalid + // we could make Coordinator death fatal, except during exit, but since + // Strands do not re-register, even process death would be pointless. + return TheInstance; +} diff --git a/src/ipc/Coordinator.h b/src/ipc/Coordinator.h index c4620dc970..f2fd75b71a 100644 --- a/src/ipc/Coordinator.h +++ b/src/ipc/Coordinator.h @@ -19,9 +19,14 @@ namespace Ipc /// Coordinates shared activities of Strands (Squid processes or threads) class Coordinator: public Port { +public: + static Coordinator* Instance(); + public: Coordinator(); + void broadcastSignal(int sig) const; ///< send sig to registered strands + protected: virtual void start(); // Port (AsyncJob) API virtual void receive(const Message& message); // Port API @@ -32,6 +37,7 @@ protected: private: Vector strands; ///< registered processes and threads + static Coordinator* TheInstance; ///< the only class instance in existence CBDATA_CLASS2(Coordinator); diff --git a/src/main.cc b/src/main.cc index 7a07e1df8b..0a8cdece32 100644 --- a/src/main.cc +++ b/src/main.cc @@ -127,6 +127,10 @@ static volatile int do_rotate = 0; static volatile int do_shutdown = 0; static volatile int shutdown_status = 0; +static int RotateSignal = -1; +static int ReconfigureSignal = -1; +static int ShutdownSignal = -1; + static void mainRotate(void); static void mainReconfigureStart(void); static void mainReconfigureFinish(void*); @@ -198,6 +202,10 @@ SignalEngine::checkEvents(int timeout) doShutdown(do_shutdown > 0 ? (int) Config.shutdownLifetime : 0); do_shutdown = 0; } + BroadcastSignalIfAny(DebugSignal); + BroadcastSignalIfAny(RotateSignal); + BroadcastSignalIfAny(ReconfigureSignal); + BroadcastSignalIfAny(ShutdownSignal); PROF_stop(SignalEngine_checkEvents); return EVENT_IDLE; @@ -556,6 +564,7 @@ void rotate_logs(int sig) { do_rotate = 1; + RotateSignal = sig; #ifndef _SQUID_MSWIN_ #if !HAVE_SIGACTION @@ -569,6 +578,7 @@ void reconfigure(int sig) { do_reconfigure = 1; + ReconfigureSignal = sig; #ifndef _SQUID_MSWIN_ #if !HAVE_SIGACTION @@ -581,6 +591,7 @@ void shut_down(int sig) { do_shutdown = sig == SIGINT ? -1 : 1; + ShutdownSignal = sig; #ifdef SIGTTIN if (SIGTTIN == sig) @@ -724,10 +735,17 @@ mainReconfigureFinish(void *) Config2.onoff.enable_purge = 2; // parse the config returns a count of errors encountered. + const int oldMainProcesses = Config.main_processes; if ( parseConfigFile(ConfigFile) != 0) { // for now any errors are a fatal condition... self_destruct(); } + if (oldMainProcesses != Config.main_processes) { + debugs(1, DBG_CRITICAL, "WARNING: Changing 'main_processes' (from " << + oldMainProcesses << " to " << Config.main_processes << + ") is not supported and ignored"); + Config.main_processes = oldMainProcesses; + } setUmask(Config.umask); Mem::Report(); @@ -1400,7 +1418,7 @@ SquidMain(int argc, char **argv) if (!opt_no_daemon && Config.main_processes > 1) { if (KidIdentifier == Config.main_processes + 1) - AsyncJob::AsyncStart(new Ipc::Coordinator); + AsyncJob::AsyncStart(Ipc::Coordinator::Instance()); else if (KidIdentifier != 0) AsyncJob::AsyncStart(new Ipc::Strand); } @@ -1826,10 +1844,12 @@ SquidShutdown() #endif - if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) { - enter_suid(); - safeunlink(Config.pidFilename, 0); - leave_suid(); + if (IsPidFileMaintainer()) { + if (Config.pidFilename && strcmp(Config.pidFilename, "none") != 0) { + enter_suid(); + safeunlink(Config.pidFilename, 0); + leave_suid(); + } } debugs(1, 1, "Squid Cache (Version " << version_string << "): Exiting normally."); diff --git a/src/protos.h b/src/protos.h index 4ff74b8fa7..b60f915e53 100644 --- a/src/protos.h +++ b/src/protos.h @@ -575,6 +575,10 @@ SQUIDCEXTERN void squid_signal(int sig, SIGHDLR *, int flags); SQUIDCEXTERN pid_t readPidFile(void); SQUIDCEXTERN void keepCapabilities(void); +SQUIDCEXTERN void BroadcastSignalIfAny(int& sig); +SQUIDCEXTERN bool IsPidFileMaintainer(); +SQUIDCEXTERN int DebugSignal; + /* AYJ debugs function to show locations being reset with memset() */ SQUIDCEXTERN void *xmemset(void *dst, int, size_t); diff --git a/src/tools.cc b/src/tools.cc index 91c2110e81..df4eeeac01 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -41,6 +41,8 @@ #include "SquidMath.h" #include "SquidTime.h" #include "ip/IpIntercept.h" +#include "ipc/Kids.h" +#include "ipc/Coordinator.h" #if HAVE_SYS_PRCTL_H #include @@ -64,6 +66,7 @@ extern void log_trace_done(); extern void log_trace_init(char *); #endif static void restoreCapabilities(int keep); +int DebugSignal = -1; #ifdef _SQUID_LINUX_ /* Workaround for crappy glic header files */ @@ -397,6 +400,17 @@ death(int sig) abort(); } +void +BroadcastSignalIfAny(int& sig) +{ + if (sig > 0) { + if (!opt_no_daemon && Config.main_processes > 1) { + if (KidIdentifier == Config.main_processes + 1) + Ipc::Coordinator::Instance()->broadcastSignal(sig); + } + sig = -1; + } +} void sigusr2_handle(int sig) @@ -404,6 +418,8 @@ sigusr2_handle(int sig) static int state = 0; /* no debugs() here; bad things happen if the signal is delivered during _db_print() */ + DebugSignal = sig; + if (state == 0) { #ifndef MEM_GEN_TRACE Debug::parseOptions("ALL,7"); @@ -790,6 +806,26 @@ no_suid(void) #endif } +bool +IsPidFileMaintainer() +{ + if (!opt_no_daemon && Config.main_processes > 0) { + if (Config.main_processes > 1) { + // multiple kids delegate PID file maintanence to the coordinator + if (KidIdentifier <= Config.main_processes) + return false; + } else { + // master process does not maintain PID file when + // Config.main_processes == 1 + if (KidIdentifier == 0) + return false; + } + } + + // if there are no kids, then the master process maintains the PID file + return true; +} + void writePidFile(void) { @@ -798,6 +834,9 @@ writePidFile(void) mode_t old_umask; char buf[32]; + if (!IsPidFileMaintainer()) + return; + if ((f = Config.pidFilename) == NULL) return;