Logo Search packages:      
Sourcecode: valknut version File versions  Download package

dcdebug.cpp

/***************************************************************************
                          dcdebug.cpp  -  description
                             -------------------
    begin                : Don Sep 25 2003
    copyright            : (C) 2003 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#endif

#include <qprocess.h>
#include <qpushbutton.h>
#include <qfile.h>
#include <qprocess.h>
#include <qapplication.h>
#include <qtextedit.h>
#include <qmessagebox.h>
#include <qfiledialog.h>

#include <dcconfig.h>
#include <dclib/dcos.h>
#include <dclib/dclib.h>
#include <dclib/chttp.h>
#include <dclib/core/cstring.h>

#include "dcdebug.h"

CString DCDebug::arg_0 = "";
CString DCDebug::startup_dir = "";

/** */
DCDebug::DCDebug( QWidget *parent, const char *name ) : DCDialogDebug(parent,name)
{
      m_pHttp = 0;

      InitDocument();
}

/** */
DCDebug::~DCDebug()
{
      m_Timer.stop();

      if ( m_pHttp )
      {
            delete m_pHttp;
      }
}

/** */
void DCDebug::InitDocument()
{
      connect( PushButton_EXIT, SIGNAL(clicked()), this, SLOT(accept()) );
      connect( PushButton_SEND, SIGNAL(clicked()), this, SLOT(slotSendBacktrace()) );
      connect( PushButton_SAVE, SIGNAL(clicked()), this, SLOT(slotSaveBacktrace()) );

      // enable timer
      connect( &m_Timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
}

/** */
bool DCDebug::Init( QString configpath, QString debugopt )
{
      bool res = FALSE;
#ifndef WIN32
      int i;
      QString s = "bt full\nq\n";
      QString filename = configpath+"/"+"gdbrc";
      QFile f(filename);
      QString s1,s2,s3;
      QProcess pr;

      m_sBuffer = "";

      s1 = debugopt.section(",",0,0);
      s2 = debugopt.section(",",1,1);
      s3 = debugopt.section(",",2,2);

      printf("Init debug:\nConfigpath: '%s'\n%s %s %s\n",
                  configpath.ascii(),
                  s1.ascii(),
                  s2.ascii(),
                  s3.ascii() ); fflush(stdout);

      f.open( IO_WriteOnly | IO_Truncate );
      f.writeBlock(s,s.length());
      f.close();

      pr.addArgument("gdb");
      pr.addArgument("--nw");
      pr.addArgument("--nx");
      pr.addArgument("--quiet");
      pr.addArgument("--batch");
      pr.addArgument("-x");
      pr.addArgument(filename);
      pr.addArgument(s3);
      pr.addArgument(s1);

      if ( pr.start() == TRUE )
      {
            while( pr.isRunning() )
            {
                  sleep(1);
            }

            QString s;
            while( (s = pr.readLineStdout()) != QString::null )
                  m_sBuffer += s + "\n";
            while( (s = pr.readLineStderr()) != QString::null )
                  m_sBuffer += s + "\n";

            s = "";

            // get version
            QFile f1("/proc/version");

            if ( f1.open( IO_ReadOnly ) )
            {
                  while ( (i=f1.getch()) != -1 )
                        s += i;

                  f1.close();

                  s += "\n";
            }

            // create output text
            s += "Valknut: ";
            s += VERSION;
            s += "\n";
            s += "DCLIB: ";
            s += dclibVersion();
            s += "\n";
            s += "QT compiled: ";
            s += QT_VERSION_STR;
            s += "\n";
            s += "QT used: ";
            s += qVersion();
            s += "\n";
            s += "LIBXML compiled: ";
            s += LIBXML_VERSION_STRING;
            s += "\n";
            s += "LIBXML used: ";
            s += xmlParserVersion;
            s += "\n\n";

            TextEdit_LOG->setText(s + m_sBuffer);

            res = TRUE;
      }
      else
      {
            // TODO: error message
            printf("start failed\n"); fflush(stdout);
      }
#endif
      return res;
}

/** */
void DCDebug::timerDone()
{
      if ( m_bTransfer == FALSE )
      {
            if ( m_pHttp )
            {
                  if ( m_pHttp->GetHttpError() != 200 )
                  {
                        QMessageBox::critical( this, tr("Send error"),
                              tr("Could not send the data. Error '%1'.").arg(m_pHttp->GetHttpError()) );

                        PushButton_SEND->setEnabled(TRUE);
                  }
                  else
                  {
                        QMessageBox::critical( this, tr("Send"),
                              tr("Thanks for your help.") );
                  }
            }

            PushButton_SAVE->setEnabled(TRUE);
            PushButton_EXIT->setEnabled(TRUE);
      }
      else
      {
            m_Timer.start( 500, TRUE );
      }
}

/** */
void DCDebug::slotSendBacktrace()
{
      QString text;

      if ( m_pHttp )
            delete m_pHttp;

      PushButton_SAVE->setEnabled(FALSE);
      PushButton_SEND->setEnabled(FALSE);
      PushButton_EXIT->setEnabled(FALSE);

      m_bTransfer = TRUE;
      m_Timer.start( 500, TRUE );

      m_pHttp = new CHttp();
      m_pHttp->SetCallBackFunction( new CCallback<DCDebug>( this, &DCDebug::HttpCallBack ) );

      text  = "--- Comment\n\n";
      text += TextEdit_COMMENT->text() + "\n";
      text += "--- Backtrace\n\n";
      text += TextEdit_LOG->text() + "\n";
      text += "--- End\n";

      m_pHttp->GetUrl("http://dcgui.berlios.de/crash.php",text.ascii());
}

/** */
void DCDebug::slotSaveBacktrace()
{
      QString s = QFileDialog::getSaveFileName(
                    "",
                    "Text (*.txt)",
                    this,
                    "save file dialog"
                    "Choose a filename to save under" );

      if ( s.isNull() )
      {
            return;
      }

      QFile *file = new QFile(s);

      if ( !file->open( IO_WriteOnly ) )
      {
            QMessageBox::critical( this, tr("Save error"),
                  tr("Can't open file '%1' for writing.").arg(s) );
      }
      else
      {
            file->writeBlock( TextEdit_LOG->text().ascii(), TextEdit_LOG->text().length() ); 
            file->close();
      }

      delete file;
}

/** http callback function */
int DCDebug::HttpCallBack( CObject *, CObject * object )
{
      switch(((CDCMessage*)object)->m_eType)
      {
            case DC_MESSAGE_CONNECTION_STATE:
            {
                  CMessageConnectionState *msg = (CMessageConnectionState*)object;

                  if ( msg->m_eState == estDISCONNECTED )
                  {
                        m_bTransfer = FALSE;
                  }

                  break;
            }

            case DC_MESSAGE_TRANSFER:
            {
                  break;
            }

            default:
            {
                  break;
            }
      }

      if ( object )
      {
            delete object;
      }

      return 0;
}

#ifndef WIN32
/** */
static void crash_handler( int sig );

/*!
 *\brief    install crash handlers
 */
void crash_install_handlers(void)
{
      sigset_t mask;
      sigemptyset(&mask);

#ifdef SIGSEGV
      signal(SIGSEGV, crash_handler);
      sigaddset(&mask, SIGSEGV);
#endif
      
#ifdef SIGFPE
      signal(SIGFPE, crash_handler);
      sigaddset(&mask, SIGFPE);
#endif

#ifdef SIGILL
      signal(SIGILL, crash_handler);
      sigaddset(&mask, SIGILL);
#endif

#ifdef SIGABRT
      signal(SIGABRT, crash_handler);
      sigaddset(&mask, SIGABRT);
#endif

#ifdef SIGTRAP
      signal(SIGTRAP, crash_handler);
      sigaddset(&mask, SIGTRAP);
#endif

#ifdef SIGTERM
//    signal(SIGTERM, crash_handler);
//    sigaddset(&mask, SIGTERM);
#endif

      sigprocmask(SIG_UNBLOCK, &mask, 0);
}

/*!
 *\brief    this handler will probably evolve into 
 *          something better.
 */
static void crash_handler(int sig)
{
      pid_t pid;
      static volatile unsigned long crashed_ = 0;
                             
      /*
       * let's hope startup_dir and argv0 aren't trashed.
       * both are defined in main.c.
       */
      if (sig < 0 || sig > 32) { /* what's that ? */
//          char *buf = g_strdup_printf(
//                      _("Caught strange signal (%d). This is probably\n"
//                        "due to a broken compilation; Exiting."), sig);
//          ay_do_error( _("Error"), buf );
//          g_free(buf);
            printf("SIGNAL_HANDLER: unknown signal %d\n",sig);
            _exit(0);
      }
      /*
       * besides guarding entrancy it's probably also better 
       * to mask off signals
       */
      if (crashed_) _exit(253);

      crashed_++;

#ifdef SIGTERM
//    if (sig == SIGTERM)
//    {
//          printf("SIGNAL_HANDLER: SIGTERM catched\n");
//          exit(1);
//    }
#endif

      printf("CRASH CRASH CRASH \n");fflush(stdout);

      QProcess pr;
      CString cp = g_pConfig->GetConfigPath().Data();

      if (0 == (pid = fork()))
      {
            char buf[50];
            char *args[6];
            CString cp = g_pConfig->GetConfigPath().Data();

            args[0] = DCDebug::arg_0.Data(); 
            args[1] = "-c";
            args[2] = cp.Data();
            args[3] = "-C";
            snprintf(buf, sizeof(buf), "%d,%d,%s", getppid(), sig, DCDebug::arg_0.Data());
            args[4] = buf;
            args[5] = NULL;

            chdir(DCDebug::startup_dir.Data());
            setgid(getgid());
            setuid(getuid());
            execvp(DCDebug::arg_0.Data(), args);
      } else {
            waitpid(pid, NULL, 0);
            _exit(253);
      }

      _exit(253);
}

#endif


Generated by  Doxygen 1.6.0   Back to index