diff options
Diffstat (limited to 'drkonqi/debugger.cpp')
-rw-r--r-- | drkonqi/debugger.cpp | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/drkonqi/debugger.cpp b/drkonqi/debugger.cpp new file mode 100644 index 000000000..95ec6c9ba --- /dev/null +++ b/drkonqi/debugger.cpp @@ -0,0 +1,219 @@ +/***************************************************************** + * drkonqi - The KDE Crash Handler + * + * Copyright (C) 2000-2003 Hans Petter Bieker <[email protected]> + * + * 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. + *****************************************************************/ + +#include <qlayout.h> +#include <qhbox.h> +#include <qlabel.h> + +#include <kdialog.h> +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> +#include <ktextbrowser.h> +#include <ktempfile.h> + +#include "backtrace.h" +#include "krashconf.h" +#include "debugger.h" +#include "debugger.moc" + +KrashDebugger :: KrashDebugger (const KrashConfig *krashconf, QWidget *parent, const char *name) + : QWidget( parent, name ), + m_krashconf(krashconf), + m_proctrace(0) +{ + QVBoxLayout *vbox = new QVBoxLayout( this, 0, KDialog::marginHint() ); + vbox->setAutoAdd(TRUE); + + m_backtrace = new KTextBrowser(this); + m_backtrace->setTextFormat(Qt::PlainText); + m_backtrace->setFont(KGlobalSettings::fixedFont()); + + QWidget *w = new QWidget( this ); + ( new QHBoxLayout( w, 0, KDialog::marginHint() ) )->setAutoAdd( true ); + m_status = new QLabel( w ); + m_status->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ) ); + //m_copyButton = new KPushButton( KStdGuiItem::copy(), w ); + KGuiItem item( i18n( "C&opy" ), QString::fromLatin1( "editcopy" ) ); + m_copyButton = new KPushButton( item, w ); + connect( m_copyButton, SIGNAL( clicked() ), this, SLOT( slotCopy() ) ); + m_copyButton->setEnabled( false ); + m_saveButton = new KPushButton( m_krashconf->safeMode() ? KStdGuiItem::save() : KStdGuiItem::saveAs(), w ); + connect( m_saveButton, SIGNAL( clicked() ), this, SLOT( slotSave() ) ); + m_saveButton->setEnabled( false ); +} + +KrashDebugger :: ~KrashDebugger() +{ + // This will SIGKILL gdb and SIGCONT program which crashed. + // delete m_proctrace; +} + +void KrashDebugger :: slotDone(const QString& str) +{ + m_status->setText(i18n("Done.")); + m_copyButton->setEnabled( true ); + m_saveButton->setEnabled( true ); + m_backtrace->setText( m_prependText + str ); // replace with possibly post-processed backtrace +} + +void KrashDebugger :: slotCopy() +{ + m_backtrace->selectAll(); + m_backtrace->copy(); +} + +void KrashDebugger :: slotSave() +{ + if (m_krashconf->safeMode()) + { + KTempFile tf(QString::fromAscii("/tmp/"), QString::fromAscii(".kcrash"), 0600); + if (!tf.status()) + { + *tf.textStream() << m_backtrace->text(); + tf.close(); + KMessageBox::information(this, i18n("Backtrace saved to %1").arg(tf.name())); + } + else + { + KMessageBox::sorry(this, i18n("Cannot create a file in which to save the backtrace")); + } + } + else + { + QString defname = m_krashconf->execName() + QString::fromLatin1( ".kcrash" ); + if( defname.contains( '/' )) + defname = defname.mid( defname.findRev( '/' ) + 1 ); + QString filename = KFileDialog::getSaveFileName(defname, QString::null, this, i18n("Select Filename")); + if (!filename.isEmpty()) + { + QFile f(filename); + + if (f.exists()) { + if (KMessageBox::Cancel == + KMessageBox::warningContinueCancel( 0, + i18n( "A file named \"%1\" already exists. " + "Are you sure you want to overwrite it?" ).arg( filename ), + i18n( "Overwrite File?" ), + i18n( "&Overwrite" ) )) + return; + } + + if (f.open(IO_WriteOnly)) + { + QTextStream ts(&f); + ts << m_backtrace->text(); + f.close(); + } + else + { + KMessageBox::sorry(this, i18n("Cannot open file %1 for writing").arg(filename)); + } + } + } +} + +void KrashDebugger :: slotSomeError() +{ + m_status->setText(i18n("Unable to create a valid backtrace.")); + m_backtrace->setText(i18n("This backtrace appears to be of no use.\n" + "This is probably because your packages are built in a way " + "which prevents creation of proper backtraces, or the stack frame " + "was seriously corrupted in the crash.\n\n" ) + + m_backtrace->text()); +} + +void KrashDebugger :: slotAppend(const QString &str) +{ + m_status->setText(i18n("Loading backtrace...")); + + // append doesn't work here because it will add a newline as well + m_backtrace->setText(m_backtrace->text() + str); +} + +void KrashDebugger :: showEvent(QShowEvent *e) +{ + QWidget::showEvent(e); + startDebugger(); +} + +void KrashDebugger :: startDebugger() +{ + // Only start one copy + if (m_proctrace || !m_backtrace->text().isEmpty()) + return; + + QString msg; + bool checks = performChecks( &msg ); + if( !checks && !m_krashconf->disableChecks()) + { + m_backtrace->setText( m_prependText + + i18n( "The following options are enabled:\n\n" ) + + msg + + i18n( "\nAs the usage of these options is not recommended -" + " because they can, in rare cases, be responsible for KDE problems - a backtrace" + " will not be generated.\n" + "You need to turn these options off and reproduce" + " the problem again in order to get a backtrace.\n" )); + m_status->setText( i18n( "Backtrace will not be created.")); + return; + } + if( !msg.isEmpty()) + { + m_prependText += msg + '\n'; + m_backtrace->setText( m_prependText ); + } + m_status->setText(i18n("Loading symbols...")); + + m_proctrace = new BackTrace(m_krashconf, this); + + connect(m_proctrace, SIGNAL(append(const QString &)), + SLOT(slotAppend(const QString &))); + connect(m_proctrace, SIGNAL(done(const QString&)), SLOT(slotDone(const QString&))); + connect(m_proctrace, SIGNAL(someError()), SLOT(slotSomeError())); + + m_proctrace->start(); +} + +// this function check for "dangerous" settings, returns false +// and message in case some of them are activated +bool KrashDebugger::performChecks( QString* msg ) +{ + bool ret = true; + KConfig kdedcfg( QString::fromLatin1( "kdedrc" ), true ); + kdedcfg.setGroup( "General" ); + if( kdedcfg.readBoolEntry( "DelayedCheck", false )) + { + // ret = false; it's not that dangerous + *msg += i18n( "System configuration startup check disabled.\n" ); + } + return ret; +} |