Properly obtain threading debug information in TDE crash handler

Fix potential TDE crash handler lockup uncer certain circumstances
Enhance crashtest program with three threads
pull/2/head
Timothy Pearson 11 years ago
parent 013eed4fdc
commit c12a32aec0

@ -176,8 +176,22 @@ void BackTrace::slotProcessExited(TDEProcess *proc)
bool BackTrace::usefulBacktrace() bool BackTrace::usefulBacktrace()
{ {
// remove crap // remove crap
if( !m_krashconf->removeFromBacktraceRegExp().isEmpty()) if( !m_krashconf->removeFromBacktraceRegExp().isEmpty()) {
m_strBt.replace(TQRegExp( m_krashconf->removeFromBacktraceRegExp()), TQString()); 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()) if( m_krashconf->disableChecks())
return true; return true;
@ -204,20 +218,32 @@ void BackTrace::processBacktrace()
{ {
if( !m_krashconf->kcrashRegExp().isEmpty()) { if( !m_krashconf->kcrashRegExp().isEmpty()) {
TQRegExp kcrashregexp( m_krashconf->kcrashRegExp()); TQRegExp kcrashregexp( m_krashconf->kcrashRegExp());
int pos = -1; kcrashregexp.setMinimal(true);
while ((pos = kcrashregexp.search( m_strBt )) >= 0) { int pos = 0;
pos = kcrashregexp.search( m_strBt ); 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 ) { if( pos >= 0 ) {
int len = kcrashregexp.matchedLength(); int len = kcrashregexp.matchedLength();
int nextinfochunkpos = m_strBt.find("====", pos); int nextinfochunkpos = m_strBt.find("====", pos);
if (nextinfochunkpos >= 0) { if (nextinfochunkpos >= 0) {
// Trying to delete too much! // Trying to delete too much!
int chunkpos = pos; int limitedlen = nextinfochunkpos - pos;
TQString limitedstrBt = m_strBt.mid(pos, nextinfochunkpos - pos); TQString limitedstrBt = m_strBt.mid(pos, limitedlen);
pos = kcrashregexp.search( limitedstrBt ) + chunkpos; int limitedpos = kcrashregexp.search( limitedstrBt );
len = kcrashregexp.matchedLength(); if (limitedpos >= 0) {
len = kcrashregexp.matchedLength();
}
else {
len = 0;
}
} }
if (pos >= 0) { if ((pos >= 0) && (len > 0)) {
if( m_strBt[ pos ] == '\n' ) { if( m_strBt[ pos ] == '\n' ) {
++pos; ++pos;
--len; --len;
@ -226,6 +252,17 @@ void BackTrace::processBacktrace()
m_strBt.insert( pos, TQString::fromLatin1( "[TDECrash handler]\n" )); 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()) { if( !m_krashconf->kcrashRegExpSingle().isEmpty()) {
@ -242,7 +279,7 @@ void BackTrace::processBacktrace()
} }
// Append potentially important hardware information // 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(); TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices(); TDEGenericHardwareList hwlist = hwdevices->listAllPhysicalDevices();
TDEGenericDevice *hwdevice; TDEGenericDevice *hwdevice;
@ -259,4 +296,14 @@ void BackTrace::processBacktrace()
m_strBt.append("\n"); 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");
}
}
} }

@ -1,11 +1,28 @@
// Let's crash. // Let's crash.
#include <unistd.h>
#include <tdeapplication.h> #include <tdeapplication.h>
#include <tdeaboutdata.h> #include <tdeaboutdata.h>
#include <tdecmdlineargs.h> #include <tdecmdlineargs.h>
#include <tqthread.h>
#include <tqtimer.h>
#include <kdebug.h> #include <kdebug.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#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[] = static TDECmdLineOptions options[] =
{ {
{ "+crash|malloc|div0|assert", "Type of crash.", 0 }, { "+crash|malloc|div0|assert", "Type of crash.", 0 },
@ -74,6 +91,17 @@ int main(int argc, char *argv[])
TDEAboutData::License_GPL, TDEAboutData::License_GPL,
"(c) 2000-2002 David Faure, Waldo Bastian"); "(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::init(argc, argv, &aboutData);
TDECmdLineArgs::addCmdLineOptions(options); TDECmdLineArgs::addCmdLineOptions(options);
@ -90,3 +118,5 @@ int main(int argc, char *argv[])
level1(crashtype); level1(crashtype);
return app.exec(); return app.exec();
} }
#include "crashtest.moc"

@ -0,0 +1,40 @@
/*****************************************************************
*
* Copyright (C) 2013 Timothy Pearson <kb9vqf@pearsoncomputing.net>
*
* 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 <tqobject.h>
class WorkerObject : public TQObject
{
Q_OBJECT
public slots:
void run();
};
#endif // CRASHTEST_H

@ -158,10 +158,11 @@ Comment[zu]=Umcoshi wamaphutha osekelwe umbhalo osuka kwi-GNU kwikhonsoli
Exec=konsole -e gdb -nw %execname %pid Exec=konsole -e gdb -nw %execname %pid
ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid
TryExec=gdb 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? RemoveFromBacktraceRegExp=\(no debugging symbols found\)\.\.\.\\n?
InvalidStackFrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ \w* \?\? InvalidStackFrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ \w* \?\?
FrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ FrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+
NeededInValidBacktraceRegExp=\\n#5 NeededInValidBacktraceRegExp=\\n#5
TDECrashRegExp=\\n#0[ ]*0x[0123456789abcdefABCDEF]+.*<signal handler called>[ ]*\\n TDECrashRegExp=\\n#0[ ]*0x[0123456789abcdefABCDEF]+.*<signal handler called>[ ]*\\n
TDECrashRegExpSingle=\\n0x[0123456789abcdefABCDEF][^\\n]*\\n TDECrashRegExpSingle=\\n0x[0123456789abcdefABCDEF][^\\n]*\\n
ThreadRegExp=\\nThread [0123456789]

@ -112,6 +112,7 @@ void KrashConfig :: readConfig()
m_neededInValidBacktraceRegExp = debuggers.readEntry("NeededInValidBacktraceRegExp"); m_neededInValidBacktraceRegExp = debuggers.readEntry("NeededInValidBacktraceRegExp");
m_kcrashRegExp = debuggers.readEntry("TDECrashRegExp"); m_kcrashRegExp = debuggers.readEntry("TDECrashRegExp");
m_kcrashRegExpSingle = debuggers.readEntry("TDECrashRegExpSingle"); m_kcrashRegExpSingle = debuggers.readEntry("TDECrashRegExpSingle");
m_threadRegExp = debuggers.readEntry("ThreadRegExp");
TDEConfig preset(TQString::fromLatin1("presets/%1rc").arg(configname), TDEConfig preset(TQString::fromLatin1("presets/%1rc").arg(configname),
true, false, "appdata"); true, false, "appdata");

@ -67,6 +67,7 @@ public:
TQString neededInValidBacktraceRegExp() const { return m_neededInValidBacktraceRegExp; } TQString neededInValidBacktraceRegExp() const { return m_neededInValidBacktraceRegExp; }
TQString kcrashRegExp() const { return m_kcrashRegExp; } TQString kcrashRegExp() const { return m_kcrashRegExp; }
TQString kcrashRegExpSingle() const { return m_kcrashRegExpSingle; } TQString kcrashRegExpSingle() const { return m_kcrashRegExpSingle; }
TQString threadRegExp() const { return m_threadRegExp; }
bool showBacktrace() const { return m_showbacktrace; }; bool showBacktrace() const { return m_showbacktrace; };
bool showDebugger() const { return m_showdebugger && !m_debugger.isNull(); }; bool showDebugger() const { return m_showdebugger && !m_debugger.isNull(); };
bool showBugReport() const { return m_showbugreport; }; bool showBugReport() const { return m_showbugreport; };
@ -110,6 +111,7 @@ private:
TQString m_neededInValidBacktraceRegExp; TQString m_neededInValidBacktraceRegExp;
TQString m_kcrashRegExp; TQString m_kcrashRegExp;
TQString m_kcrashRegExpSingle; TQString m_kcrashRegExpSingle;
TQString m_threadRegExp;
}; };
#endif #endif

Loading…
Cancel
Save