From c12a32aec01bb5f6956ecfcd086997322eb7ec68 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 25 May 2013 19:34:47 -0500 Subject: Properly obtain threading debug information in TDE crash handler Fix potential TDE crash handler lockup uncer certain circumstances Enhance crashtest program with three threads --- drkonqi/backtrace.cpp | 67 +++++++++++++++++++++++++++++++++++++++++-------- drkonqi/crashtest.cpp | 30 ++++++++++++++++++++++ drkonqi/crashtest.h | 40 +++++++++++++++++++++++++++++ drkonqi/debuggers/gdbrc | 3 ++- drkonqi/krashconf.cpp | 1 + drkonqi/krashconf.h | 2 ++ 6 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 drkonqi/crashtest.h (limited to 'drkonqi') diff --git a/drkonqi/backtrace.cpp b/drkonqi/backtrace.cpp index 2b349d288..61ae8130c 100644 --- a/drkonqi/backtrace.cpp +++ b/drkonqi/backtrace.cpp @@ -176,8 +176,22 @@ void BackTrace::slotProcessExited(TDEProcess *proc) bool BackTrace::usefulBacktrace() { // remove crap - if( !m_krashconf->removeFromBacktraceRegExp().isEmpty()) + if( !m_krashconf->removeFromBacktraceRegExp().isEmpty()) { m_strBt.replace(TQRegExp( m_krashconf->removeFromBacktraceRegExp()), TQString()); + } + + // fix threading info output + if( !m_krashconf->threadRegExp().isEmpty()) { + int pos = -1; + TQRegExp threadRegExpression( m_krashconf->threadRegExp()); + do { + threadRegExpression.search(m_strBt); + pos = threadRegExpression.pos(); + if (pos > -1) { + m_strBt.insert(threadRegExpression.pos()+1, "==== "); + } + } while (pos > -1); + } if( m_krashconf->disableChecks()) return true; @@ -204,20 +218,32 @@ void BackTrace::processBacktrace() { if( !m_krashconf->kcrashRegExp().isEmpty()) { TQRegExp kcrashregexp( m_krashconf->kcrashRegExp()); - int pos = -1; - while ((pos = kcrashregexp.search( m_strBt )) >= 0) { - pos = kcrashregexp.search( m_strBt ); + kcrashregexp.setMinimal(true); + int pos = 0; + int prevpos = 0; + while ((pos = kcrashregexp.search( m_strBt, pos )) >= 0) { + if (prevpos == pos) { + // Avoid infinite loop + // Shouldn't ever get here, but given that this is a crash handler, better safe than sorry! + break; + } + prevpos = pos; if( pos >= 0 ) { int len = kcrashregexp.matchedLength(); int nextinfochunkpos = m_strBt.find("====", pos); if (nextinfochunkpos >= 0) { // Trying to delete too much! - int chunkpos = pos; - TQString limitedstrBt = m_strBt.mid(pos, nextinfochunkpos - pos); - pos = kcrashregexp.search( limitedstrBt ) + chunkpos; - len = kcrashregexp.matchedLength(); + int limitedlen = nextinfochunkpos - pos; + TQString limitedstrBt = m_strBt.mid(pos, limitedlen); + int limitedpos = kcrashregexp.search( limitedstrBt ); + if (limitedpos >= 0) { + len = kcrashregexp.matchedLength(); + } + else { + len = 0; + } } - if (pos >= 0) { + if ((pos >= 0) && (len > 0)) { if( m_strBt[ pos ] == '\n' ) { ++pos; --len; @@ -226,6 +252,17 @@ void BackTrace::processBacktrace() m_strBt.insert( pos, TQString::fromLatin1( "[TDECrash handler]\n" )); } } + if (pos < 0) { + // Avoid infinite loop + // Shouldn't ever get here, but given that this is a crash handler, better safe than sorry! + break; + } + pos++; + if ((uint)pos >= m_strBt.length()) { + // Avoid infinite loop + // Shouldn't ever get here, but given that this is a crash handler, better safe than sorry! + break; + } } } if( !m_krashconf->kcrashRegExpSingle().isEmpty()) { @@ -242,7 +279,7 @@ void BackTrace::processBacktrace() } // Append potentially important hardware information - m_strBt.append("\n\n==== (tdehwlib) hardware information ====\n"); + m_strBt.append("\n==== (tdehwlib) hardware information ====\n"); TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices(); TDEGenericDevice *hwdevice; @@ -259,4 +296,14 @@ void BackTrace::processBacktrace() m_strBt.append("\n"); } } + + { + // Clean up hard to read debug blocks + TQRegExp kcrashregexp( "[^\n]\n==== "); + kcrashregexp.setMinimal(true); + int pos = 0; + while ((pos = kcrashregexp.search( m_strBt, pos )) >= 0) { + m_strBt.insert(pos+1, "\n"); + } + } } diff --git a/drkonqi/crashtest.cpp b/drkonqi/crashtest.cpp index 2583c1273..ff38fae24 100644 --- a/drkonqi/crashtest.cpp +++ b/drkonqi/crashtest.cpp @@ -1,11 +1,28 @@ // Let's crash. +#include #include #include #include +#include +#include #include #include #include +#include "crashtest.h" + +void WorkerObject::run() +{ + while (1) { + sleep(10000); + } +} + +#define SET_UP_WORKER(x, y) \ + WorkerObject x; \ + x.moveToThread(&y); \ + TQTimer::singleShot(0, &x, SLOT(run())); + static TDECmdLineOptions options[] = { { "+crash|malloc|div0|assert", "Type of crash.", 0 }, @@ -74,6 +91,17 @@ int main(int argc, char *argv[]) TDEAboutData::License_GPL, "(c) 2000-2002 David Faure, Waldo Bastian"); + // Start 3 threads + TQEventLoopThread workerthread0; + TQEventLoopThread workerthread1; + TQEventLoopThread workerthread2; + SET_UP_WORKER(worker0, workerthread0) + SET_UP_WORKER(worker1, workerthread1) + SET_UP_WORKER(worker2, workerthread2) + workerthread0.start(); + workerthread1.start(); + workerthread2.start(); + TDECmdLineArgs::init(argc, argv, &aboutData); TDECmdLineArgs::addCmdLineOptions(options); @@ -90,3 +118,5 @@ int main(int argc, char *argv[]) level1(crashtype); return app.exec(); } + +#include "crashtest.moc" \ No newline at end of file diff --git a/drkonqi/crashtest.h b/drkonqi/crashtest.h new file mode 100644 index 000000000..482c410ca --- /dev/null +++ b/drkonqi/crashtest.h @@ -0,0 +1,40 @@ +/***************************************************************** + * + * Copyright (C) 2013 Timothy Pearson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************/ + +#ifndef CRASHTEST_H +#define CRASHTEST_H + +#include + +class WorkerObject : public TQObject +{ + Q_OBJECT + + public slots: + void run(); +}; + +#endif // CRASHTEST_H \ No newline at end of file diff --git a/drkonqi/debuggers/gdbrc b/drkonqi/debuggers/gdbrc index e414d86a0..1aa1f8c36 100644 --- a/drkonqi/debuggers/gdbrc +++ b/drkonqi/debuggers/gdbrc @@ -158,10 +158,11 @@ Comment[zu]=Umcoshi wamaphutha osekelwe umbhalo osuka kwi-GNU kwikhonsoli Exec=konsole -e gdb -nw %execname %pid ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid TryExec=gdb -BacktraceCommand=echo \\n\necho ==== (gdb) bt ====\\n\nbt\necho \\n\\n\necho ==== (gdb) bt full ====\\n\nbt full\necho\\n\\n\necho ==== (gdb) thread apply all bt ====\\n\nthread apply all bt +BacktraceCommand=echo \\n\necho ==== (gdb) bt ====\\n\nbt\necho \\n\\n\necho ==== (gdb) bt full ====\\n\nbt full\necho\\n\\n\necho ==== (gdb) info thread ====\\n\ninfo thread\necho\\n\\n\necho ==== (gdb) thread apply all bt ====\\n\nthread apply all bt RemoveFromBacktraceRegExp=\(no debugging symbols found\)\.\.\.\\n? InvalidStackFrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ \w* \?\? FrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ NeededInValidBacktraceRegExp=\\n#5 TDECrashRegExp=\\n#0[ ]*0x[0123456789abcdefABCDEF]+.*[ ]*\\n TDECrashRegExpSingle=\\n0x[0123456789abcdefABCDEF][^\\n]*\\n +ThreadRegExp=\\nThread [0123456789] diff --git a/drkonqi/krashconf.cpp b/drkonqi/krashconf.cpp index 6a96c4aab..84bbfee8c 100644 --- a/drkonqi/krashconf.cpp +++ b/drkonqi/krashconf.cpp @@ -112,6 +112,7 @@ void KrashConfig :: readConfig() m_neededInValidBacktraceRegExp = debuggers.readEntry("NeededInValidBacktraceRegExp"); m_kcrashRegExp = debuggers.readEntry("TDECrashRegExp"); m_kcrashRegExpSingle = debuggers.readEntry("TDECrashRegExpSingle"); + m_threadRegExp = debuggers.readEntry("ThreadRegExp"); TDEConfig preset(TQString::fromLatin1("presets/%1rc").arg(configname), true, false, "appdata"); diff --git a/drkonqi/krashconf.h b/drkonqi/krashconf.h index 2e4c414ee..074cfce6f 100644 --- a/drkonqi/krashconf.h +++ b/drkonqi/krashconf.h @@ -67,6 +67,7 @@ public: TQString neededInValidBacktraceRegExp() const { return m_neededInValidBacktraceRegExp; } TQString kcrashRegExp() const { return m_kcrashRegExp; } TQString kcrashRegExpSingle() const { return m_kcrashRegExpSingle; } + TQString threadRegExp() const { return m_threadRegExp; } bool showBacktrace() const { return m_showbacktrace; }; bool showDebugger() const { return m_showdebugger && !m_debugger.isNull(); }; bool showBugReport() const { return m_showbugreport; }; @@ -110,6 +111,7 @@ private: TQString m_neededInValidBacktraceRegExp; TQString m_kcrashRegExp; TQString m_kcrashRegExpSingle; + TQString m_threadRegExp; }; #endif -- cgit v1.2.1