]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug #2224 fix: reentrant debugging crashes Squid
authorrousskov <>
Wed, 27 Feb 2008 01:43:30 +0000 (01:43 +0000)
committerrousskov <>
Wed, 27 Feb 2008 01:43:30 +0000 (01:43 +0000)
Reentrant debugging occurs when something being written into the debugging
stream produces its own debugging. For example, a field accessor method may
make cbdata-validation calls, which would produce debugging. Logging such
field would crash Squid if sufficiently high debugging level is enabled.

With this change, the Debug methods detect reentrant calls and mostly ignore
them, allowing the caller to append debugging information to the existing
debug stream. A short debugging label is added before and after the reentrant
debugging message to reduce confusion that overlapping debugging statements
may cause during log analysis.

src/Debug.h
src/debug.cc

index 3c01c6e11bb2d5dd9baf5cceb5223980ce519541..daab4715604ff738c7e8d130e1830deb6760788a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: Debug.h,v 1.12 2008/01/11 05:04:02 amosjeffries Exp $
+ * $Id: Debug.h,v 1.13 2008/02/26 18:43:30 rousskov Exp $
  *
  * DEBUG: section 0     Debug Routines
  * AUTHOR: Harvest Derived
@@ -69,7 +69,11 @@ public:
     static void parseOptions(char const *);
 
 private:
+    // Hack: replaces global ::xassert() to debug debugging assertions
+    static void xassert(const char *msg, const char *file, int line);
+       
     static std::ostringstream *CurrentDebug;
+    static int TheDepth; // level of nested debugging calls
 };
 
 /* Debug stream */
index 3e8a4b72edfe73c56c10f77ff2ebbb3b06465ea0..cfe2ebc63a4a370b0e836b7d83eda8e9050f9802 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: debug.cc,v 1.108 2007/12/29 18:20:22 hno Exp $
+ * $Id: debug.cc,v 1.109 2008/02/26 18:43:30 rousskov Exp $
  *
  * DEBUG: section 0     Debug Routines
  * AUTHOR: Harvest Derived
@@ -735,21 +735,50 @@ ctx_get_descr(Ctx ctx) {
     return Ctx_Descrs[ctx] ? Ctx_Descrs[ctx] : "<null>";
 }
 
+int Debug::TheDepth = 0;
+
 std::ostream &
 Debug::getDebugOut() {
-    assert (CurrentDebug == NULL);
-    CurrentDebug = new std::ostringstream();
-    // set default formatting flags
-    CurrentDebug->setf(std::ios::fixed);
-    CurrentDebug->precision(2);
+    assert(TheDepth >= 0);
+    ++TheDepth;
+    if (TheDepth > 1) {
+        assert(CurrentDebug);
+        *CurrentDebug << std::endl << "reentrant debuging " << TheDepth << "-{";
+    } else {
+        assert(!CurrentDebug);
+        CurrentDebug = new std::ostringstream();
+        // set default formatting flags
+        CurrentDebug->setf(std::ios::fixed);
+        CurrentDebug->precision(2);
+    }
     return *CurrentDebug;
 }
 
 void
 Debug::finishDebug() {
-    _db_print("%s\n", CurrentDebug->str().c_str());
-    delete CurrentDebug;
-    CurrentDebug = NULL;
+    assert(TheDepth >= 0);
+    assert(CurrentDebug);
+    if (TheDepth > 1) {
+        *CurrentDebug << "}-" << TheDepth << std::endl;
+    } else {
+        assert(TheDepth == 1);
+        _db_print("%s\n", CurrentDebug->str().c_str());
+        delete CurrentDebug;
+        CurrentDebug = NULL;
+    }
+    --TheDepth;
+}
+
+// Hack: replaces global ::xassert() to debug debugging assertions
+// Relies on assert macro calling xassert() without a specific scope.
+void
+Debug::xassert(const char *msg, const char *file, int line) {
+       
+    if (CurrentDebug) {
+        *CurrentDebug << "assertion failed: " << file << ":" << line <<
+            ": \"" << msg << "\"";
+    }
+    abort();
 }
 
 std::ostringstream (*Debug::CurrentDebug)(NULL);