This change also reduces libdebug dependency on globals.cc, improving
libdebug reusability.
Also do not default-reset debug sections after they were explicitly set:
* In most sbin/squid contexts, DebugModule constructor is called before
Debug::parseOptions(). That call order results in the Levels array
being reset to default values before it is reset to configured values.
No problem.
* In sbin/squid -X context, DebugModule constructor is called after
Debug::parseOptions(), but the override_X flag protected the Levels
array from being reset to default values in this case. No problem.
* In helper contexts, DebugModule constructor may be called after
Debug::parseOptions(), and the override_X flag stays false. This order
results in the parseOptions() effects erased by ResetSections() called
from the constructor.
This bug was detected while trying to understand why pinger's hard-coded
(and wrong) ALL,10 default has no effect on pinger's debugging. The two
bugs cancelled each other.
The following changes affect pinger (now) and other helpers that will
eventually use libdebug and its new NameThisHelper() API:
* Label helper debugs() lines with the helper name (e.g., "pinger"),
similar to how we already label SMP debugs() lines with "kidN". This
change improves cache.log readability, distinguishes output from
different helpers, and distinguishes helper output from sbin/squid
output in non-SMP logs.
* Make sure level-1 debugs() messages are logged.
* Stop pointless accumulation of cache.log and syslog channel messages.
* Automatically honor SQUID_DEBUG environment variable set by the parent
Squid process. The pinger helper was already honoring it.
The following changes are specific to pinger:
* Removed the now-duplicated references to "pinger" in pinger debugs().
* Do not default pinger debugging levels to ALL,10. The default pinger
debugging levels should be the same as the default Squid debugging
levels (i.e. "ALL,1"). Bugs in the debugging module prevented the
hard-coded "ALL,10" (or any other elevated setting) from having an
effect, but we now fixed the last of those bugs. AFAICT, the change of
default from ALL,1 to ALL,10 in commit
cc192b5 was accidental.
static int override_X;
static bool log_syslog;
+ // TODO: Convert all helpers to use debugs() and NameThisHelper() APIs.
+ /// Use the given name for debugs() messages from this helper process.
+ /// Side effect: Commits to using helper-appropriate debug levels/channels.
+ /// \sa NameThisKid()
+ static void NameThisHelper(const char *name);
+
+ /// Use the given ID for debugs() messages from this SMP kid process.
+ /// \sa NameThisHelper()
+ static void NameThisKid(int kidIdentifier);
+
static void parseOptions(char const *);
/// minimum level required by the current debugs() call
/// early debugs() with higher level are not buffered and, hence, may be lost
static constexpr int EarlyMessagesLevel = DBG_IMPORTANT;
+/// pre-formatted name of the current process for debugs() messages (or empty)
+static std::string ProcessLabel;
+
static const char *debugLogTime(time_t t);
-static const char *debugLogKid(void);
+
#if HAVE_SYSLOG
#ifdef LOG_LOCAL4
static int syslog_facility = 0;
static void ResetSections(const int level = DBG_IMPORTANT);
+/// Whether ResetSections() has been called already. We need to keep track of
+/// this state because external code may trigger ResetSections() before the
+/// DebugModule constructor has a chance to ResetSections() to their defaults.
+/// TODO: Find a way to static-initialize Debug::Levels instead.
+static bool DidResetSections = false;
+
/// a named FILE with very-early/late usage safety mechanisms
class DebugFile
{
static void
ResetSections(const int level)
{
+ DidResetSections = true;
for (auto §ionLevel: Debug::Levels)
sectionLevel = level;
}
+/// optimization: formats ProcessLabel once for frequent debugs() reuse
+static void
+LabelThisProcess(const char * const name, const Optional<int> id = Optional<int>())
+{
+ assert(name);
+ assert(strlen(name));
+ std::stringstream os;
+ os << ' ' << name;
+ if (id.has_value()) {
+ assert(id.value() >= 0);
+ os << id.value();
+ }
+ ProcessLabel = os.str();
+}
+
+void
+Debug::NameThisHelper(const char * const name)
+{
+ LabelThisProcess(name);
+
+ if (const auto parentProcessDebugOptions = getenv("SQUID_DEBUG")) {
+ assert(!debugOptions);
+ debugOptions = xstrdup(parentProcessDebugOptions);
+ }
+
+ // do not restrict helper (i.e. stderr) logging beyond debug_options
+ EnsureDefaultStderrLevel(DBG_DATA);
+
+ // helpers do not write to cache.log directly; instead, ipcCreate()
+ // diverts helper stderr output to cache.log of the parent process
+ BanCacheLogUse();
+
+ SettleStderr();
+ SettleSyslog();
+}
+
+void
+Debug::NameThisKid(const int kidIdentifier)
+{
+ // to reduce noise and for backward compatibility, do not label kid messages
+ // in non-SMP mode
+ if (kidIdentifier)
+ LabelThisProcess("kid", Optional<int>(kidIdentifier));
+ else
+ ProcessLabel.clear(); // probably already empty
+}
+
/* LoggingSectionGuard */
LoggingSectionGuard::LoggingSectionGuard()
(void)std::atexit(&Debug::PrepareToDie);
- if (!Debug::override_X)
+ if (!DidResetSections)
ResetSections();
}
{
fprintf(&destination, "%s%s| %s\n",
debugLogTime(header.timestamp),
- debugLogKid(),
+ ProcessLabel.c_str(),
body.c_str());
noteWritten(header);
}
return buf;
}
-static const char *
-debugLogKid(void)
-{
- if (KidIdentifier != 0) {
- static char buf[16];
- if (!*buf) // optimization: fill only once after KidIdentifier is set
- snprintf(buf, sizeof(buf), " kid%d", KidIdentifier);
- return buf;
- }
-
- return "";
-}
-
/// Whether there are any xassert() calls in the call stack. Treat as private to
/// xassert(): It is moved out only to simplify the asserting code path.
static auto Asserting_ = false;
}
icmp_ident = getpid() & 0xffff;
- debugs(42, DBG_IMPORTANT, "pinger: ICMP socket opened.");
+ debugs(42, DBG_IMPORTANT, "ICMP socket opened.");
return icmp_sock;
}
}
icmp_ident = getpid() & 0xffff;
- debugs(42, DBG_IMPORTANT, "pinger: ICMPv6 socket opened");
+ debugs(42, DBG_IMPORTANT, "ICMPv6 socket opened");
return icmp_sock;
}
}
getCurrentTime();
- debugs(42, DBG_IMPORTANT, "pinger: Squid socket opened");
+ debugs(42, DBG_IMPORTANT, "Squid socket opened");
/* windows uses a socket stream as a dual-direction channel */
socket_to_squid = icmp_sock;
if (send(socket_to_squid, &preply, len, 0) < 0) {
int xerrno = errno;
- debugs(42, DBG_CRITICAL, "FATAL: pinger: send failure: " << xstrerr(xerrno));
+ debugs(42, DBG_CRITICAL, "FATAL: send failure: " << xstrerr(xerrno));
Close();
exit(EXIT_FAILURE);
}
int icmp6_worker = -1;
int squid_link = -1;
- /** start by initializing the pinger debug cache.log-pinger. */
- const auto envOptions = getenv("SQUID_DEBUG");
- Debug::debugOptions = xstrdup(envOptions ? envOptions : "ALL,10");
+ Debug::NameThisHelper("pinger");
getCurrentTime();
// determine IPv4 or IPv6 capabilities before using sockets.
Ip::ProbeTransport();
- Debug::BanCacheLogUse();
-
- debugs(42, DBG_CRITICAL, "pinger: Initialising ICMP pinger ...");
+ debugs(42, DBG_CRITICAL, "Initialising ICMP pinger ...");
icmp4_worker = icmp4.Open();
if (icmp4_worker < 0) {
- debugs(42, DBG_CRITICAL, "ERROR: pinger: Unable to start ICMP pinger.");
+ debugs(42, DBG_CRITICAL, "ERROR: Unable to start ICMP pinger.");
}
max_fd = max(max_fd, icmp4_worker);
#if USE_IPV6
icmp6_worker = icmp6.Open();
if (icmp6_worker <0 ) {
- debugs(42, DBG_CRITICAL, "ERROR: pinger: Unable to start ICMPv6 pinger.");
+ debugs(42, DBG_CRITICAL, "ERROR: Unable to start ICMPv6 pinger.");
}
max_fd = max(max_fd, icmp6_worker);
#endif
/** abort if neither worker could open a socket. */
if (icmp4_worker < 0 && icmp6_worker < 0) {
- debugs(42, DBG_CRITICAL, "FATAL: pinger: Unable to open any ICMP sockets.");
+ debugs(42, DBG_CRITICAL, "FATAL: Unable to open any ICMP sockets.");
exit(EXIT_FAILURE);
}
if ( (squid_link = control.Open()) < 0) {
- debugs(42, DBG_CRITICAL, "FATAL: pinger: Unable to setup Pinger control sockets.");
+ debugs(42, DBG_CRITICAL, "FATAL: Unable to setup Pinger control sockets.");
icmp4.Close();
icmp6.Close();
exit(EXIT_FAILURE); // fatal error if the control channel fails.
if (setgid(getgid()) < 0) {
int xerrno = errno;
- debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerr(xerrno));
+ debugs(42, DBG_CRITICAL, "FATAL: setgid(" << getgid() << ") failed: " << xstrerr(xerrno));
icmp4.Close();
icmp6.Close();
exit(EXIT_FAILURE);
}
if (setuid(getuid()) < 0) {
int xerrno = errno;
- debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerr(xerrno));
+ debugs(42, DBG_CRITICAL, "FATAL: setuid(" << getuid() << ") failed: " << xstrerr(xerrno));
icmp4.Close();
icmp6.Close();
exit(EXIT_FAILURE);
caps = cap_init();
if (!caps) {
int xerrno = errno;
- debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_init() failed: " << xstrerr(xerrno));
+ debugs(42, DBG_CRITICAL, "FATAL: cap_init() failed: " << xstrerr(xerrno));
icmp4.Close();
icmp6.Close();
exit(EXIT_FAILURE);
if (cap_set_proc(caps) != 0) {
int xerrno = errno;
// cap_set_proc(cap_init()) is expected to never fail
- debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_set_proc(none) failed: " << xstrerr(xerrno));
+ debugs(42, DBG_CRITICAL, "FATAL: cap_set_proc(none) failed: " << xstrerr(xerrno));
cap_free(caps);
icmp4.Close();
icmp6.Close();
if (PINGER_TIMEOUT + last_check_time < squid_curtime) {
if (send(LINK_TO_SQUID, &tv, 0, 0) < 0) {
- debugs(42, DBG_CRITICAL, "pinger: Closing. No requests in last " << PINGER_TIMEOUT << " seconds.");
+ debugs(42, DBG_CRITICAL, "Closing. No requests in last " << PINGER_TIMEOUT << " seconds.");
control.Close();
exit(EXIT_FAILURE);
}
TheKidName.assign(APP_SHORTNAME);
KidIdentifier = 0;
}
+ Debug::NameThisKid(KidIdentifier);
}
/// Start directing debugs() messages to the configured cache.log.