debug.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 00 Debug Routines */
10 
11 #include "squid.h"
12 #include "base/TextException.h"
13 #include "Debug.h"
14 #include "DebugMessages.h"
15 #include "fd.h"
16 #include "ipc/Kids.h"
17 #include "SquidTime.h"
18 #include "util.h"
19 
20 #include <algorithm>
21 
22 /* for shutting_down flag in xassert() */
23 #include "globals.h"
24 
26 int Debug::override_X = 0;
27 int Debug::log_stderr = -1;
28 bool Debug::log_syslog = false;
30 char *Debug::cache_log = NULL;
31 int Debug::rotateNumber = -1;
33 static const char *debugLogTime(void);
34 static const char *debugLogKid(void);
35 #if HAVE_SYSLOG
36 #ifdef LOG_LOCAL4
37 static int syslog_facility = 0;
38 #endif
39 static void _db_print_syslog(const bool forceAlert, const char *format, va_list args);
40 #endif
41 static void _db_print_stderr(const char *format, va_list args);
42 static void _db_print_file(const char *format, va_list args);
43 
44 #if _SQUID_WINDOWS_
45 extern LPCRITICAL_SECTION dbg_mutex;
46 typedef BOOL (WINAPI * PFInitializeCriticalSectionAndSpinCount) (LPCRITICAL_SECTION, DWORD);
47 #endif
48 
50 class DebugFile
51 {
52 public:
53  DebugFile() {}
54  ~DebugFile() { clear(); }
55  DebugFile(DebugFile &&) = delete; // no copying or moving of any kind
56 
58  void reset(FILE *newFile, const char *newName);
59 
61  void clear() { reset(nullptr, nullptr); }
62 
64  FILE *file() { return file_ ? file_ : stderr; }
65 
66  char *name = nullptr;
67 
68 private:
69  friend void ResyncDebugLog(FILE *newFile);
70 
71  FILE *file_ = nullptr;
72 };
73 
77 
78 FILE *
80  return TheLog.file();
81 }
82 
83 void
85 {
86  TheLog.clear();
87 }
88 
89 void
90 ResyncDebugLog(FILE *newFile)
91 {
92  TheLog.file_ = newFile;
93 }
94 
95 void
96 DebugFile::reset(FILE *newFile, const char *newName)
97 {
98  // callers must use nullptr instead of the used-as-the-last-resort stderr
99  assert(newFile != stderr || !stderr);
100 
101  if (file_) {
102  fd_close(fileno(file_));
103  fclose(file_);
104  }
105  file_ = newFile; // may be nil
106 
107  if (file_)
109 
110  xfree(name);
111  name = newName ? xstrdup(newName) : nullptr;
112 
113  // all open files must have a name
114  // all cleared files must not have a name
115  assert(!file_ == !name);
116 }
117 
118 static
119 void
120 _db_print(const bool forceAlert, const char *format,...)
121 {
122  char f[BUFSIZ];
123  f[0]='\0';
124  va_list args1;
125  va_list args2;
126  va_list args3;
127 
128 #if _SQUID_WINDOWS_
129  /* Multiple WIN32 threads may call this simultaneously */
130 
131  if (!dbg_mutex) {
132  HMODULE krnl_lib = GetModuleHandle("Kernel32");
133  PFInitializeCriticalSectionAndSpinCount InitializeCriticalSectionAndSpinCount = NULL;
134 
135  if (krnl_lib)
136  InitializeCriticalSectionAndSpinCount =
137  (PFInitializeCriticalSectionAndSpinCount) GetProcAddress(krnl_lib,
138  "InitializeCriticalSectionAndSpinCount");
139 
140  dbg_mutex = static_cast<CRITICAL_SECTION*>(xcalloc(1, sizeof(CRITICAL_SECTION)));
141 
142  if (InitializeCriticalSectionAndSpinCount) {
143  /* let multiprocessor systems EnterCriticalSection() fast */
144 
145  if (!InitializeCriticalSectionAndSpinCount(dbg_mutex, 4000)) {
146  if (debug_log) {
147  fprintf(debug_log, "FATAL: _db_print: can't initialize critical section\n");
148  fflush(debug_log);
149  }
150 
151  fprintf(stderr, "FATAL: _db_print: can't initialize critical section\n");
152  abort();
153  } else
154  InitializeCriticalSection(dbg_mutex);
155  }
156  }
157 
158  EnterCriticalSection(dbg_mutex);
159 #endif
160 
161  va_start(args1, format);
162  va_start(args2, format);
163  va_start(args3, format);
164 
165  snprintf(f, BUFSIZ, "%s%s| %s",
166  debugLogTime(),
167  debugLogKid(),
168  format);
169 
170  _db_print_file(f, args1);
171  _db_print_stderr(f, args2);
172 
173 #if HAVE_SYSLOG
174  _db_print_syslog(forceAlert, format, args3);
175 #else
176  (void)forceAlert;
177 #endif
178 
179 #if _SQUID_WINDOWS_
180  LeaveCriticalSection(dbg_mutex);
181 #endif
182 
183  va_end(args1);
184  va_end(args2);
185  va_end(args3);
186 }
187 
188 static void
189 _db_print_file(const char *format, va_list args)
190 {
191  if (debug_log == NULL)
192  return;
193 
194  vfprintf(debug_log, format, args);
195  fflush(debug_log);
196 }
197 
198 static void
199 _db_print_stderr(const char *format, va_list args)
200 {
202  return;
203 
204  if (debug_log == stderr)
205  return;
206 
207  vfprintf(stderr, format, args);
208 }
209 
210 #if HAVE_SYSLOG
211 static void
212 _db_print_syslog(const bool forceAlert, const char *format, va_list args)
213 {
214  /* level 0,1 go to syslog */
215 
216  if (!forceAlert) {
217  if (Debug::Level() > 1)
218  return;
219 
220  if (!Debug::log_syslog)
221  return;
222  }
223 
224  char tmpbuf[BUFSIZ];
225  tmpbuf[0] = '\0';
226 
227  vsnprintf(tmpbuf, BUFSIZ, format, args);
228 
229  tmpbuf[BUFSIZ - 1] = '\0';
230 
231  syslog(forceAlert ? LOG_ALERT : (Debug::Level() == 0 ? LOG_WARNING : LOG_NOTICE), "%s", tmpbuf);
232 }
233 #endif /* HAVE_SYSLOG */
234 
235 static void
236 debugArg(const char *arg)
237 {
238  int s = 0;
239  int l = 0;
240  int i;
241 
242  if (!strncasecmp(arg, "rotate=", 7)) {
243  arg += 7;
244  Debug::rotateNumber = atoi(arg);
245  return;
246  } else if (!strncasecmp(arg, "ALL", 3)) {
247  s = -1;
248  arg += 4;
249  } else {
250  s = atoi(arg);
251  while (*arg && *arg++ != ',');
252  }
253 
254  l = atoi(arg);
255  assert(s >= -1);
256 
257  if (s >= MAX_DEBUG_SECTIONS)
258  s = MAX_DEBUG_SECTIONS-1;
259 
260  if (l < 0)
261  l = 0;
262 
263  if (l > 10)
264  l = 10;
265 
266  if (s >= 0) {
267  Debug::Levels[s] = l;
268  return;
269  }
270 
271  for (i = 0; i < MAX_DEBUG_SECTIONS; ++i)
272  Debug::Levels[i] = l;
273 }
274 
275 static void
276 debugOpenLog(const char *logfile)
277 {
278  if (logfile == NULL) {
279  TheLog.clear();
280  return;
281  }
282 
283  // Bug 4423: ignore the stdio: logging module name if present
284  const char *logfilename;
285  if (strncmp(logfile, "stdio:",6) == 0)
286  logfilename = logfile + 6;
287  else
288  logfilename = logfile;
289 
290  if (auto log = fopen(logfilename, "a+")) {
291 #if _SQUID_WINDOWS_
292  setmode(fileno(log), O_TEXT);
293 #endif
294  TheLog.reset(log, logfilename);
295  } else {
296  fprintf(stderr, "WARNING: Cannot write log file: %s\n", logfile);
297  perror(logfile);
298  fprintf(stderr, " messages will be sent to 'stderr'.\n");
299  fflush(stderr);
300  TheLog.clear();
301  }
302 }
303 
304 #if HAVE_SYSLOG
305 #ifdef LOG_LOCAL4
306 
307 static struct syslog_facility_name {
308  const char *name;
309  int facility;
310 }
311 
312 syslog_facility_names[] = {
313 
314 #ifdef LOG_AUTH
315  {
316  "auth", LOG_AUTH
317  },
318 #endif
319 #ifdef LOG_AUTHPRIV
320  {
321  "authpriv", LOG_AUTHPRIV
322  },
323 #endif
324 #ifdef LOG_CRON
325  {
326  "cron", LOG_CRON
327  },
328 #endif
329 #ifdef LOG_DAEMON
330  {
331  "daemon", LOG_DAEMON
332  },
333 #endif
334 #ifdef LOG_FTP
335  {
336  "ftp", LOG_FTP
337  },
338 #endif
339 #ifdef LOG_KERN
340  {
341  "kern", LOG_KERN
342  },
343 #endif
344 #ifdef LOG_LPR
345  {
346  "lpr", LOG_LPR
347  },
348 #endif
349 #ifdef LOG_MAIL
350  {
351  "mail", LOG_MAIL
352  },
353 #endif
354 #ifdef LOG_NEWS
355  {
356  "news", LOG_NEWS
357  },
358 #endif
359 #ifdef LOG_SYSLOG
360  {
361  "syslog", LOG_SYSLOG
362  },
363 #endif
364 #ifdef LOG_USER
365  {
366  "user", LOG_USER
367  },
368 #endif
369 #ifdef LOG_UUCP
370  {
371  "uucp", LOG_UUCP
372  },
373 #endif
374 #ifdef LOG_LOCAL0
375  {
376  "local0", LOG_LOCAL0
377  },
378 #endif
379 #ifdef LOG_LOCAL1
380  {
381  "local1", LOG_LOCAL1
382  },
383 #endif
384 #ifdef LOG_LOCAL2
385  {
386  "local2", LOG_LOCAL2
387  },
388 #endif
389 #ifdef LOG_LOCAL3
390  {
391  "local3", LOG_LOCAL3
392  },
393 #endif
394 #ifdef LOG_LOCAL4
395  {
396  "local4", LOG_LOCAL4
397  },
398 #endif
399 #ifdef LOG_LOCAL5
400  {
401  "local5", LOG_LOCAL5
402  },
403 #endif
404 #ifdef LOG_LOCAL6
405  {
406  "local6", LOG_LOCAL6
407  },
408 #endif
409 #ifdef LOG_LOCAL7
410  {
411  "local7", LOG_LOCAL7
412  },
413 #endif
414  {
415  NULL, 0
416  }
417 };
418 
419 #endif
420 
421 void
422 _db_set_syslog(const char *facility)
423 {
424  Debug::log_syslog = true;
425 
426 #ifdef LOG_LOCAL4
427 #ifdef LOG_DAEMON
428 
429  syslog_facility = LOG_DAEMON;
430 #else
431 
432  syslog_facility = LOG_LOCAL4;
433 #endif /* LOG_DAEMON */
434 
435  if (facility) {
436 
437  struct syslog_facility_name *n;
438 
439  for (n = syslog_facility_names; n->name; ++n) {
440  if (strcmp(n->name, facility) == 0) {
441  syslog_facility = n->facility;
442  return;
443  }
444  }
445 
446  fprintf(stderr, "unknown syslog facility '%s'\n", facility);
447  exit(EXIT_FAILURE);
448  }
449 
450 #else
451  if (facility)
452  fprintf(stderr, "syslog facility type not supported on your system\n");
453 
454 #endif /* LOG_LOCAL4 */
455 }
456 
457 #else /* HAVE_SYSLOG */
458 
459 void
460 _db_set_syslog(const char *)
461 {
462  throw TextException("Logging to syslog is not available on this platform", Here());
463 }
464 
465 #endif
466 
467 void
468 Debug::parseOptions(char const *options)
469 {
470  int i;
471  char *p = NULL;
472  char *s = NULL;
473 
474  if (override_X) {
475  debugs(0, 9, "command-line -X overrides: " << options);
476  return;
477  }
478 
479  for (i = 0; i < MAX_DEBUG_SECTIONS; ++i)
480  Debug::Levels[i] = 0;
481 
482  if (options) {
483  p = xstrdup(options);
484 
485  for (s = strtok(p, w_space); s; s = strtok(NULL, w_space))
486  debugArg(s);
487 
488  xfree(p);
489  }
490 }
491 
492 void
493 _db_init(const char *logfile, const char *options)
494 {
495  Debug::parseOptions(options);
496 
498 
499 #if HAVE_SYSLOG && defined(LOG_LOCAL4)
500 
501  if (Debug::log_syslog)
502  openlog(APP_SHORTNAME, LOG_PID | LOG_NDELAY | LOG_CONS, syslog_facility);
503 
504 #endif /* HAVE_SYSLOG */
505 
506  /* Pre-Init TZ env, see bug #2656 */
507  tzset();
508 }
509 
510 void
512 {
513  if (!TheLog.name)
514  return;
515 
516 #ifdef S_ISREG
517  struct stat sb;
518  if (stat(TheLog.name, &sb) == 0)
519  if (S_ISREG(sb.st_mode) == 0)
520  return;
521 #endif
522 
523  char from[MAXPATHLEN];
524  from[0] = '\0';
525 
526  char to[MAXPATHLEN];
527  to[0] = '\0';
528 
529  /*
530  * NOTE: we cannot use xrename here without having it in a
531  * separate file -- tools.c has too many dependencies to be
532  * used everywhere debug.c is used.
533  */
534  /* Rotate numbers 0 through N up one */
535  for (int i = Debug::rotateNumber; i > 1;) {
536  --i;
537  snprintf(from, MAXPATHLEN, "%s.%d", TheLog.name, i - 1);
538  snprintf(to, MAXPATHLEN, "%s.%d", TheLog.name, i);
539 #if _SQUID_WINDOWS_
540  remove
541  (to);
542 #endif
543  errno = 0;
544  if (rename(from, to) == -1) {
545  const auto saved_errno = errno;
546  debugs(0, DBG_IMPORTANT, "log rotation failed: " << xstrerr(saved_errno));
547  }
548  }
549 
550  /* Rotate the current log to .0 */
551  if (Debug::rotateNumber > 0) {
552  // form file names before we may clear TheLog below
553  snprintf(from, MAXPATHLEN, "%s", TheLog.name);
554  snprintf(to, MAXPATHLEN, "%s.%d", TheLog.name, 0);
555 
556 #if _SQUID_WINDOWS_
557  errno = 0;
558  if (remove(to) == -1) {
559  const auto saved_errno = errno;
560  debugs(0, DBG_IMPORTANT, "removal of log file " << to << " failed: " << xstrerr(saved_errno));
561  }
562  TheLog.clear(); // Windows cannot rename() open files
563 #endif
564  errno = 0;
565  if (rename(from, to) == -1) {
566  const auto saved_errno = errno;
567  debugs(0, DBG_IMPORTANT, "renaming file " << from << " to "
568  << to << "failed: " << xstrerr(saved_errno));
569  }
570  }
571 
572  // Close (if we have not already) and reopen the log because
573  // it may have been renamed "manually" before HUP'ing us.
575 }
576 
577 static const char *
579 {
580 
581  time_t t = getCurrentTime();
582 
583  struct tm *tm;
584  static char buf[128]; // arbitrary size, big enough for the below timestamp strings.
585  static time_t last_t = 0;
586 
587  if (Debug::Level() > 1) {
588  // 4 bytes smaller than buf to ensure .NNN catenation by snprintf()
589  // is safe and works even if strftime() fills its buffer.
590  char buf2[sizeof(buf)-4];
591  tm = localtime(&t);
592  strftime(buf2, sizeof(buf2), "%Y/%m/%d %H:%M:%S", tm);
593  buf2[sizeof(buf2)-1] = '\0';
594  const int sz = snprintf(buf, sizeof(buf), "%s.%03d", buf2, static_cast<int>(current_time.tv_usec / 1000));
595  assert(0 < sz && sz < static_cast<int>(sizeof(buf)));
596  last_t = t;
597  } else if (t != last_t) {
598  tm = localtime(&t);
599  const int sz = strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", tm);
600  assert(0 < sz && sz <= static_cast<int>(sizeof(buf)));
601  last_t = t;
602  }
603 
604  buf[sizeof(buf)-1] = '\0';
605  return buf;
606 }
607 
608 static const char *
610 {
611  if (KidIdentifier != 0) {
612  static char buf[16];
613  if (!*buf) // optimization: fill only once after KidIdentifier is set
614  snprintf(buf, sizeof(buf), " kid%d", KidIdentifier);
615  return buf;
616  }
617 
618  return "";
619 }
620 
621 void
622 xassert(const char *msg, const char *file, int line)
623 {
624  debugs(0, DBG_CRITICAL, "assertion failed: " << file << ":" << line << ": \"" << msg << "\"");
625 
626  if (!shutting_down)
627  abort();
628 }
629 
630 Debug::Context *Debug::Current = nullptr;
631 
632 Debug::Context::Context(const int aSection, const int aLevel):
633  level(aLevel),
634  sectionLevel(Levels[aSection]),
635  upper(Current),
636  forceAlert(false)
637 {
638  formatStream();
639 }
640 
642 void
643 Debug::Context::rewind(const int aSection, const int aLevel)
644 {
645  level = aLevel;
646  sectionLevel = Levels[aSection];
647  assert(upper == Current);
648 
649  buf.str(std::string());
650  buf.clear();
651  // debugs() users are supposed to preserve format, but
652  // some do not, so we have to waste cycles resetting it for all.
653  formatStream();
654 }
655 
657 void
659 {
660  const static std::ostringstream cleanStream;
661  buf.flags(cleanStream.flags() | std::ios::fixed);
662  buf.width(cleanStream.width());
663  buf.precision(2);
664  buf.fill(' ');
665  // If this is not enough, use copyfmt(cleanStream) which is ~10% slower.
666 }
667 
668 std::ostringstream &
669 Debug::Start(const int section, const int level)
670 {
671  Context *future = nullptr;
672 
673  // prepare future context
674  if (Current) {
675  // all reentrant debugs() calls get here; create a dedicated context
676  future = new Context(section, level);
677  } else {
678  // Optimization: Nearly all debugs() calls get here; avoid allocations
679  static Context *topContext = new Context(1, 1);
680  topContext->rewind(section, level);
681  future = topContext;
682  }
683 
684  Current = future;
685 
686  return future->buf;
687 }
688 
689 void
691 {
692  // TODO: #include "base/CodeContext.h" instead if doing so works well.
693  extern std::ostream &CurrentCodeContextDetail(std::ostream &os);
694  if (Current->level <= DBG_IMPORTANT)
696 
697  // TODO: Optimize to remove at least one extra copy.
698  _db_print(Current->forceAlert, "%s\n", Current->buf.str().c_str());
699  Current->forceAlert = false;
700 
701  Context *past = Current;
702  Current = past->upper;
703  if (Current)
704  delete past;
705  // else it was a static topContext from Debug::Start()
706 }
707 
708 void
710 {
711  // the ForceAlert(ostream) manipulator should only be used inside debugs()
712  if (Current)
713  Current->forceAlert = true;
714 }
715 
716 std::ostream&
717 ForceAlert(std::ostream& s)
718 {
720  return s;
721 }
722 
723 void
724 PrintHex(std::ostream &os, const char *data, const size_t n)
725 {
726  if (!n)
727  return;
728  assert(data);
729 
730  const auto savedFill = os.fill('0');
731  const auto savedFlags = os.flags(); // std::ios_base::fmtflags
732  os << std::hex;
733  std::for_each(data, data + n,
734  [&os](const char &c) { os << std::setw(2) << static_cast<uint8_t>(c); });
735  os.flags(savedFlags);
736  os.fill(savedFill);
737 }
738 
739 std::ostream &
740 Raw::print(std::ostream &os) const
741 {
742  if (label_)
743  os << ' ' << label_ << '[' << size_ << ']';
744 
745  if (!size_)
746  return os;
747 
748  // finalize debugging level if no level was set explicitly via minLevel()
749  const int finalLevel = (level >= 0) ? level :
750  (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
751  if (finalLevel <= Debug::SectionLevel()) {
752  if (label_)
753  os << '=';
754  else if (useGap_)
755  os << ' ';
756  if (data_) {
757  if (useHex_)
758  PrintHex(os, data_, size_);
759  else
760  os.write(data_, size_);
761  } else {
762  os << "[null]";
763  }
764  }
765 
766  return os;
767 }
768 
static char * debugOptions
Definition: Debug.h:75
const char * xstrerr(int error)
Definition: xstrerror.cc:83
static char * cache_log
Definition: Debug.h:76
static const char * debugLogKid(void)
Definition: debug.cc:609
static void _db_print_stderr(const char *format, va_list args)
Definition: debug.cc:199
void * xcalloc(size_t n, size_t sz)
Definition: xalloc.cc:71
#define Here()
source code location of the caller
Definition: Here.h:15
bool forceAlert
the current debugs() will be a syslog ALERT
Definition: Debug.h:66
#define BUFSIZ
Definition: defines.h:20
DebugMessages TheDebugMessages
Definition: debug.cc:32
void ResyncDebugLog(FILE *newFile)
a hack for low-level file descriptor manipulations in ipcCreate()
Definition: debug.cc:90
std::ostringstream buf
debugs() output sink
Definition: Debug.h:65
void log(char *format,...)
void _db_rotate_log(void)
Definition: debug.cc:511
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
Definition: Debug.h:109
int KidIdentifier
#define O_TEXT
Definition: defines.h:140
FILE * file()
logging stream; the only method that uses stderr as the last resort
Definition: debug.cc:64
#define xstrdup
@ FD_LOG
Definition: enums.h:14
SQUIDCEXTERN LPCRITICAL_SECTION dbg_mutex
Definition: WinSvc.cc:48
Context(const int aSectionLevel, const int aLevel)
Definition: debug.cc:632
static std::ostringstream & Start(const int section, const int level)
opens debugging context and returns output buffer
Definition: debug.cc:669
static void debugOpenLog(const char *logfile)
Definition: debug.cc:276
#define DBG_CRITICAL
Definition: Debug.h:40
static void _db_print(const bool forceAlert, const char *format,...)
Definition: debug.cc:120
static DebugFile TheLog
Definition: debug.cc:76
void xassert(const char *msg, const char *file, int line)
Definition: debug.cc:622
time_t getCurrentTime(void)
Get current time.
#define DBG_IMPORTANT
Definition: Debug.h:41
#define w_space
static void debugArg(const char *arg)
Definition: debug.cc:236
static int SectionLevel()
maximum level currently allowed
Definition: Debug.h:88
#define MAX_DEBUG_SECTIONS
Definition: Debug.h:37
void clear()
go back to the initial state
Definition: debug.cc:61
int level
minimum debugging level required by the debugs() call
Definition: Debug.h:57
#define APP_SHORTNAME
Definition: version.h:22
static FILE * logfile
static const char * debugLogTime(void)
Definition: debug.cc:578
~DebugFile()
Definition: debug.cc:54
static int Levels[MAX_DEBUG_SECTIONS]
Definition: Debug.h:78
void _db_set_syslog(const char *)
Definition: debug.cc:460
#define NULL
Definition: types.h:166
void StopUsingDebugLog()
start logging to stderr (instead of cache.log, if any)
Definition: debug.cc:84
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
meta-information for debugs() or a similar debugging call
Definition: Debug.h:53
static void Finish()
logs output buffer created in Start() and closes debugging context
Definition: debug.cc:690
Context * upper
previous or parent record in nested debugging calls
Definition: Debug.h:64
DebugFile(DebugFile &&)=delete
void formatStream()
configures default formatting for the debugging stream
Definition: debug.cc:658
std::ostream & print(std::ostream &os) const
Definition: debug.cc:740
#define assert(EX)
Definition: assert.h:19
static void parseOptions(char const *)
Definition: debug.cc:468
static int rotateNumber
Definition: Debug.h:77
std::ostream & CurrentCodeContextDetail(std::ostream &os)
Definition: CodeContext.cc:94
void reset(FILE *newFile, const char *newName)
switches to the new pair, absorbing FILE and duping the name
Definition: debug.cc:96
void const char int sz
Definition: stub_cbdata.cc:16
#define xfree
static bool log_syslog
Definition: Debug.h:81
void rewind(const int aSection, const int aLevel)
Optimization: avoids new Context creation for every debugs().
Definition: debug.cc:643
a collection of DebugMessage objects (with fast access by message IDs)
Definition: DebugMessages.h:69
friend void ResyncDebugLog(FILE *newFile)
a hack for low-level file descriptor manipulations in ipcCreate()
Definition: debug.cc:90
struct timeval current_time
Definition: stub_time.cc:15
static void ForceAlert()
configures the active debugging context to write syslog ALERT
Definition: debug.cc:709
an std::runtime_error with thrower location info
Definition: TextException.h:20
static int Level()
minimum level required by the current debugs() call
Definition: Debug.h:86
void fd_open(int fd, unsigned int type, const char *desc)
Definition: fd.cc:157
static int override_X
Definition: Debug.h:79
a (FILE*, file name) pair that uses stderr FILE as the last resort
Definition: debug.cc:51
DebugFile()
Definition: debug.cc:53
int shutting_down
void _db_init(const char *logfile, const char *options)
Definition: debug.cc:493
#define MAXPATHLEN
Definition: stdio.h:62
static struct stat sb
Definition: squidclient.cc:71
static int log_stderr
Definition: Debug.h:80
void fd_close(int fd)
Definition: fd.cc:82
void PrintHex(std::ostream &os, const char *data, const size_t n)
Prints the first n data bytes using hex notation. Does nothing if n is 0.
Definition: debug.cc:724
static void _db_print_file(const char *format, va_list args)
Definition: debug.cc:189
T & for_each(L const &head, T &visitor)
Definition: Generic.h:23
static StatHist s
#define false
Definition: GnuRegex.c:233
static Context * Current
deepest active context; nil outside debugs()
Definition: Debug.h:102
#define BOOL
Definition: std-includes.h:38
FILE * file_
opened "real" file or nil; never stderr
Definition: debug.cc:71
#define DBG_DATA
Definition: Debug.h:43
char * name
Definition: debug.cc:66
FILE * DebugStream()
Definition: debug.cc:79

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors