]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Designate one process to maintain the PID file. Coordinator does that
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 26 Apr 2010 07:53:14 +0000 (01:53 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 26 Apr 2010 07:53:14 +0000 (01:53 -0600)
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 <PID file>`" work for SMP Squid.

src/ipc/Coordinator.cc
src/ipc/Coordinator.h
src/main.cc
src/protos.h
src/tools.cc

index b0e4893e249a8f6db6f1a51b7e32bf5bf945a430..6976b1c5ab03f1a6aab6b1fba2c4a0b22310aa5f 100644 (file)
@@ -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<StrandData>::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;
+}
index c4620dc97026510803e67b36f8d7733dbab8b8df..f2fd75b71a737ad187f2f979dfb25571ac15b635 100644 (file)
@@ -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<StrandData> strands; ///< registered processes and threads
+    static Coordinator* TheInstance; ///< the only class instance in existence
 
     CBDATA_CLASS2(Coordinator);
 
index 7a07e1df8b04706e960e4b9d4e84d3aafe482319..0a8cdece3286504ce032fe8891b31dbbcfa52aa9 100644 (file)
@@ -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.");
index 4ff74b8fa7a1f45f10cc155717db9d82d3322d91..b60f915e53c315471fcb1175787982251b513a35 100644 (file)
@@ -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);
 
index 91c2110e8162c8547ffd69a20672ed0d450e9e4d..df4eeeac01d615a6dfc12904ec1e4d78ffa16100 100644 (file)
@@ -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 <sys/prctl.h>
@@ -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;