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.
CBDATA_NAMESPACED_CLASS_INIT(Ipc, Coordinator);
+Ipc::Coordinator* Ipc::Coordinator::TheInstance = NULL;
Ipc::Coordinator::Coordinator():
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;
+}
/// 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
private:
Vector<StrandData> strands; ///< registered processes and threads
+ static Coordinator* TheInstance; ///< the only class instance in existence
CBDATA_CLASS2(Coordinator);
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*);
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;
rotate_logs(int sig)
{
do_rotate = 1;
+ RotateSignal = sig;
#ifndef _SQUID_MSWIN_
#if !HAVE_SIGACTION
reconfigure(int sig)
{
do_reconfigure = 1;
+ ReconfigureSignal = sig;
#ifndef _SQUID_MSWIN_
#if !HAVE_SIGACTION
shut_down(int sig)
{
do_shutdown = sig == SIGINT ? -1 : 1;
+ ShutdownSignal = sig;
#ifdef SIGTTIN
if (SIGTTIN == sig)
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();
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);
}
#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.");
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);
#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>
extern void log_trace_init(char *);
#endif
static void restoreCapabilities(int keep);
+int DebugSignal = -1;
#ifdef _SQUID_LINUX_
/* Workaround for crappy glic header files */
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)
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");
#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)
{
mode_t old_umask;
char buf[32];
+ if (!IsPidFileMaintainer())
+ return;
+
if ((f = Config.pidFilename) == NULL)
return;