From: <sv...@va...> - 2010-01-27 22:55:06
|
Author: cerion Date: 2010-01-27 22:54:53 +0000 (Wed, 27 Jan 2010) New Revision: 472 Log: Vk now supports running a valgrind process. That process' stdout/err are forwarded to vk's stdout/err respectively. However, stdin is not forwarded. If this is a problem for people, we'll deal with it then. Still needs lots of errorchecks, +++. Added: branches/valkyrie_qt4port/utils/vk_logpoller.cpp branches/valkyrie_qt4port/utils/vk_logpoller.h Modified: branches/valkyrie_qt4port/mainwindow.cpp branches/valkyrie_qt4port/mainwindow.h branches/valkyrie_qt4port/objects/helgrind_object.h branches/valkyrie_qt4port/objects/memcheck_object.cpp branches/valkyrie_qt4port/objects/memcheck_object.h branches/valkyrie_qt4port/objects/tool_object.cpp branches/valkyrie_qt4port/objects/tool_object.h branches/valkyrie_qt4port/objects/valkyrie_object.cpp branches/valkyrie_qt4port/objects/valkyrie_object.h branches/valkyrie_qt4port/toolview/vglogview.cpp branches/valkyrie_qt4port/toolview/vglogview.h branches/valkyrie_qt4port/utils/vk_utils.h branches/valkyrie_qt4port/valkyrie.pro Modified: branches/valkyrie_qt4port/mainwindow.cpp =================================================================== --- branches/valkyrie_qt4port/mainwindow.cpp 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/mainwindow.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -33,6 +33,7 @@ #include "help/help_context.h" #include "help/help_urls.h" #include "options/vk_option.h" +#include "objects/tool_object.h" #include "utils/vk_config.h" #include "utils/vk_messages.h" #include "utils/vk_utils.h" @@ -399,12 +400,13 @@ nextView = nextTool->createView( this ); vk_assert( nextView != 0 ); - /* TODO - connect( nextTool, SIGNAL(running(bool)), - this, SLOT(updateButtons(bool)) ); - connect( nextTool, SIGNAL(message(QString)), - this, SLOT(setStatus(QString)) ); + connect( nextTool, SIGNAL(running(bool)), + this, SLOT(updateButtons(bool)) ); +*/ + connect( nextTool, SIGNAL(message(QString)), + this, SLOT(setStatus(QString)) ); +/* TODO connect( this, SIGNAL(toolbarLabelsToggled(bool)), nextView, SLOT(toggleToolbarLabels(bool)) ); */ @@ -421,6 +423,7 @@ toolViewStack->raiseView( nextView ); setToggles( toolId ); + updateVgFlags(); } @@ -567,6 +570,27 @@ /*! + Called by this->showToolView(), + and optionsDlg::flagsChanged() signal +*/ +void MainWindow::updateVgFlags() +{ + // update valkyrie's flags: if there's a visible ToolView + if ( toolViewStack->isVisible() ) + valkyrie->updateVgFlags( toolViewStack->currentToolId() ); + +//TODO: maybe. +#if 0 + // update flags display + if ( m_flagsLabel->isVisible() ) { + showFlagsWidget( true ); + } +#endif +} + + + +/*! Calls showToolView() for a chosen valgrind tool. This slot is called by a trigger of the tool actionGroup, which is @@ -604,12 +628,16 @@ optionsDialog->activateWindow(); #else VkOptionsDialog optionsDlg( this ); + + // let the flags widget know that flags may have been modified + connect( &optionsDlg, SIGNAL(flagsChanged()), + this, SLOT(updateVgFlags()) ); + optionsDlg.exec(); #endif } - /*! Run the valgrind tool process. */ @@ -623,7 +651,7 @@ vk_assert( procId >= 0 ); // don't come in here if there's no current view - if ( toolViewStack->isVisible() == 0 ) { + if ( !toolViewStack->isVisible() ) { //This should never happen... assert? cerr << "Error: No toolview visible!" << endl; return; @@ -666,23 +694,25 @@ actProcess_Run->setEnabled( false ); actProcess_Stop->setEnabled( true ); -#if 0 - /* don't come in here if there's no current view */ - if ( m_viewStack->visible() == 0 ) + // don't come in here if there's no current view + if ( !toolViewStack->isVisible() ) return; /* valkyrie may have been started with no executable specified. if so, show prefsWindow + msgbox */ - if ( vkConfig->rdEntry("binary","valkyrie").isEmpty() ) { + if ( vkConfig->value( "valkyrie/binary").toString().isEmpty() ) { +//TODO + cerr << "Error: no binary specified!" << endl; +#if 0 showOptionsWindow( Valkyrie::ID_VALKYRIE ); - vkInfo( m_optionsWin, "Run Valgrind", + vkInfo( optionsWin, "Run Valgrind", "Please enter the path to the executable " "you wish to run, together with any arguments"); +#endif return; } - run( VkRunState::VALGRIND ); -#endif + runTool( TOOL::PROC_VALGRIND ); } Modified: branches/valkyrie_qt4port/mainwindow.h =================================================================== --- branches/valkyrie_qt4port/mainwindow.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/mainwindow.h 2010-01-27 22:54:53 UTC (rev 472) @@ -73,6 +73,7 @@ void openAboutVk(); void openAboutLicense(); void openAboutSupport(); + void updateVgFlags(); private: Valkyrie* valkyrie; Modified: branches/valkyrie_qt4port/objects/helgrind_object.h =================================================================== --- branches/valkyrie_qt4port/objects/helgrind_object.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/helgrind_object.h 2010-01-27 22:54:53 UTC (rev 472) @@ -55,8 +55,10 @@ int checkOptArg( int optid, QString& argval ); VkOptionsPage* createVkOptionsPage(); - bool start( int procId, QStringList vgflags ) { return true; } + bool start( int procId, QStringList vgflags ) { return false; } void stop() {} + + bool runValgrind( QStringList vgflags ) { return false; } }; Modified: branches/valkyrie_qt4port/objects/memcheck_object.cpp =================================================================== --- branches/valkyrie_qt4port/objects/memcheck_object.cpp 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/memcheck_object.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -24,29 +24,33 @@ #include "objects/valkyrie_object.h" #include "utils/vk_config.h" #include "utils/vk_messages.h" +#include "utils/vk_utils.h" // vk_assert, VK_DEBUG, etc. #include "utils/vglogreader.h" #include "options/vk_option.h" // PERROR* and friends //#include "vk_file_utils.h" // FileCopy() -#include "utils/vk_utils.h" // vk_assert, VK_DEBUG, etc. #include <QApplication> +#include <QDir> +#include <QTimer> +#define TIMEOUT_STOPPROC 2000 // msec until stop process +#define TIMEOUT_KILLPROC 2000 // msec until kill process (after tried to stop) + + /*! class Memcheck */ Memcheck::Memcheck() : ToolObject( "memcheck", VGTOOL::ID_MEMCHECK ) { -#if 0 /* init vars */ - m_fileSaved = true; - m_vgproc = 0; - m_vgreader = 0; - m_logpoller = new VkLogPoller( this, "memcheck logpoller" ); - connect( m_logpoller, SIGNAL(logUpdated()), + fileSaved = true; + vgproc = 0; + vgreader = 0; + logpoller = new VkLogPoller( this, "memcheck logpoller" ); + connect( logpoller, SIGNAL(logUpdated()), this, SLOT(readVgLog()) ); -#endif setupOptions(); } @@ -54,26 +58,25 @@ Memcheck::~Memcheck() { -#if 0 - if (m_vgproc) { - m_vgproc->disconnect(); /* so no signal calling processDone() */ - if (m_vgproc->isRunning()) { - m_vgproc->stop(); + if (vgproc) { + vgproc->disconnect(); // so no signal calling processDone() + if ( vgproc->state() != QProcess::NotRunning ) { + vgproc->terminate(); + //TODO: wait a short while before deleting? } - delete m_vgproc; - m_vgproc = 0; + delete vgproc; + vgproc = 0; } - if (m_vgreader) { - delete m_vgreader; - m_vgreader = 0; + if (vgreader) { + delete vgreader; + vgreader = 0; } - /* m_logpoller deleted by it's parent: 'this' */ + // logpoller deleted by it's parent: 'this' - /* unsaved log... delete our temp file */ - if (!m_fileSaved && !m_saveFname.isEmpty()) - QDir().remove( m_saveFname ); -#endif + // unsaved log... delete our temp file + if (!fileSaved && !saveFname.isEmpty()) + QDir().remove( saveFname ); } @@ -267,16 +270,16 @@ toolView = new MemcheckView( parent ); #if 0 - /* signals view --> tool */ - connect( m_view, SIGNAL(saveLogFile()), + // signals tool_view --> tool_obj + connect( toolView, SIGNAL(saveLogFile()), this, SLOT(fileSaveDialog()) ); - /* signals tool --> view */ + // signals tool_obj --> tool_view connect( this, SIGNAL(running(bool)), - m_view, SLOT(setState(bool)) ); + toolView, SLOT(setState(bool)) ); +#endif + setProcessId( TOOL::PROC_NONE ); - setRunState( VkRunState::STOPPED ); -#endif return toolView; } @@ -284,8 +287,7 @@ /* outputs a message to the status bar. */ void Memcheck::statusMsg( QString hdr, QString msg ) { -//TODO -// emit message( hdr + ": " + msg ); + emit message( hdr + ": " + msg ); } @@ -299,7 +301,7 @@ /* if current process is not yet finished, ask user if they really want to close */ if ( isRunning() ) { - int ok = vkQuery( view(), "Process Running", "&Abort;&Cancel", + int ok = vkQuery( getToolView(), "Process Running", "&Abort;&Cancel", "<p>The current process is not yet finished.</p>" "<p>Do you want to abort it ?</p>" ); /* Note: process may have finished while waiting for user */ @@ -328,8 +330,8 @@ /* currently loaded / parsed stuff is saved to tmp file - ask user if they want to save it to a 'real' file */ - if ( !m_fileSaved ) { - int ok = vkQuery( view(), "Unsaved File", + if ( !fileSaved ) { + int ok = vkQuery( getToolView(), "Unsaved File", "&Save;&Discard;&Cancel", "<p>The current output is not saved, " " and will be deleted.<br/>" @@ -345,8 +347,8 @@ } else if ( ok == MsgBox::vkCancel ) { /* procrastinate */ return false; } else { /* discard */ - QFile::remove( m_saveFname ); - m_fileSaved = true; + QFile::remove( saveFname ); + fileSaved = true; } } #endif @@ -359,20 +361,18 @@ cerr << "Memcheck::start(): " << procId << endl; vk_assert( procId > MEMCHECK_VIEW::PROC_NOPROC ); - -//TODO -// vk_assert( rs != VkRunState::STOPPED ); -// vk_assert( !isRunning() ); + vk_assert( procId > TOOL::PROC_NONE ); + vk_assert( !isRunning() ); bool ok = false; switch ( procId ) { - case MEMCHECK_VIEW::PROC_RUN_VALGRIND: + case TOOL::PROC_VALGRIND: ok = runValgrind( vgflags ); break; - case MEMCHECK_VIEW::PROC_PARSE_LOGFILE: + case MEMCHECK::PROC_PARSE_LOG: ok = parseLogFile(); break; -//TODO: maybe. +//TODO: maybe someday. // case merge: ok = mergeLogFiles(); break; default: vk_assert_never_reached(); @@ -382,47 +382,70 @@ } -/* stop a process - - doesn't exit until process stopped. - - may take some time for process to respond: too much time and it - just gets terminated. */ +/*! + Stop a process. + Try to be nice, but in case doesn't work, setup timer to guarantee it dies. +//TODO: Perhaps the view want's to hang around and wait until process is dead. but that's up to the view. +*/ void Memcheck::stop() { -#if 0 if ( !isRunning() ) return; - switch ( runState() ) { - case VkRunState::VALGRIND: { - if (m_vgproc && m_vgproc->isRunning() ) - m_vgproc->stop(); /* signal -> processDone() */ + // whatever else we do, stop trying to read from the log. + if ( logpoller ) + logpoller->stop(); + + switch ( getProcessId() ) { + case TOOL::PROC_VALGRIND: { + if ( vgproc && ( vgproc->state() != QProcess::NotRunning ) ) { + vkPrint("Memcheck::stop(): process starting/running: terminate."); + + vgproc->terminate(); // if & when succeeds: signal -> processDone() + + // in case doesn't want to stop, start timer to really kill it off. + QTimer::singleShot( TIMEOUT_KILLPROC, this, SLOT( killProc() ) ); + } + else { + vkPrint("Memcheck::stop(): process was already stopped."); + } } break; - case VkRunState::TOOL1: { /* parse log */ - /* TODO: make log parsing a VkProcess. This will allow - - valkyrie to stay responsive - - the ability to interrupt the process if taking too long */ + case MEMCHECK::PROC_PARSE_LOG: { // parse log + // TODO VK_DEBUG("TODO: Memcheck::stop(parse log)" ); } break; - case VkRunState::TOOL2: { /* merge logs */ - if (m_vgproc && m_vgproc->isRunning() ) - m_vgproc->stop(); /* signal -> processDone() */ +#if 0 + case TODO: { // merge logs + if (vgproc && vgproc->isRunning() ) + vgproc->stop(); // signal -> processDone() } break; - +#endif default: vk_assert_never_reached(); } - /* spin until done */ - while ( isRunning() ) - qApp->processEvents(); -#endif - return; } +/*! + Kills a process immediately + - only called as a result of kill timer timeout +*/ +void Memcheck::killProcess() +{ + if ( vgproc && ( vgproc->state() != QProcess::NotRunning ) ) { +vkPrint("Memcheck::killProcess(): kill the process"); + vgproc->kill(); // process will die, then signal -> processDone() + } + else { +vkPrint("Memcheck::killProcess(): process already stopped."); + } +} + + /* If --vg-opt=<arg> was specified on the cmd-line, called by valkyrie->runTool(); if set via the run-button in the gui, then MainWindow::run() calls valkyrie->runTool(). @@ -431,41 +454,42 @@ */ bool Memcheck::runValgrind( QStringList vgflags ) { -#if 0 - m_saveFname = vk_mkstemp( QString( get_VK_LOGS_DIR() ) - + "mc_log", "xml" ); - vk_assert( !m_saveFname.isEmpty() ); +//TODO: saveFname = vk_mkstemp( QString( get_VK_LOGS_DIR() ) + "mc_log", "xml" ); + saveFname = "./mc_log.xml"; + vk_assert( !saveFname.isEmpty() ); - vgflags.insert( ++(vgflags.begin()), ("--log-file=" + m_saveFname) ); + vgflags.insert( ++(vgflags.begin()), ("--log-file=" + saveFname) ); + vgflags.insert( ++(vgflags.begin()), "--xml=yes" ); - setRunState( VkRunState::VALGRIND ); - m_fileSaved = false; + setProcessId( TOOL::PROC_VALGRIND ); + fileSaved = false; statusMsg( "Memcheck", "Running ... " ); bool ok = startProcess( vgflags ); if (!ok) { statusMsg( "Memcheck", "Failed" ); - m_fileSaved = true; - setRunState( VkRunState::STOPPED ); + fileSaved = true; + setProcessId( TOOL::PROC_NONE ); } + return ok; -#endif - return true; } -/* Parse log file given by [valkyrie::view-log] entry. - Called by valkyrie->runTool() if cmdline --view-log=<file> specified. - MemcheckView::openLogFile() if gui parse-log selected. - If 'checked' == true, file perms/format has already been checked */ +/*! + Parse log file given by [valkyrie::view-log] entry. + Called by valkyrie->runTool() if cmdline --view-log=<file> specified. + MemcheckView::openLogFile() if gui parse-log selected. + If 'checked' == true, file perms/format has already been checked +*/ bool Memcheck::parseLogFile() { vk_assert( getToolView() != 0 ); //TODO: pass this via flags from the toolview, or something. QString log_file = vkConfig->value( "valkyrie/view-log" ).toString(); -// statusMsg( "Parsing", log_file ); + statusMsg( "Parsing", log_file ); //TODO: file checks #if 0 @@ -473,7 +497,7 @@ int errval = PARSED_OK; QString ret_file = fileCheck( &errval, log_file, true, false ); if ( errval != PARSED_OK ) { - vkError( view(), "File Error", "%s: \n\"%s\"", + vkError( getToolView(), "File Error", "%s: \n\"%s\"", parseErrString(errval), escapeEntities(log_file).latin1() ); return false; @@ -482,8 +506,8 @@ #endif // fileSaved true, 'cos we're just parsing an existing file -// m_fileSaved = true; -// setRunState( VkRunState::TOOL1 ); + fileSaved = true; + setProcessId( MEMCHECK::PROC_PARSE_LOG ); // Could be a very large file, so at least get ui up-to-date now qApp->processEvents( QEventLoop::AllEvents, 1000/*max msecs*/ ); @@ -498,15 +522,14 @@ "<p>%s</p>", qPrintable( escapeEntities(hnd->fatalMsg()) ) ); } -#if 0 if (success) { - m_saveFname = log_file; + saveFname = log_file; statusMsg( "Loaded", log_file ); } else { statusMsg( "Parse failed", log_file ); } - setRunState( VkRunState::STOPPED ); -#endif + setProcessId( TOOL::PROC_NONE ); + return success; } @@ -520,31 +543,32 @@ */ bool Memcheck::mergeLogFiles() { +//TODO. maybe. #if 0 QString fname_logList = vkConfig->rdEntry( "merge", "valkyrie" ); statusMsg( "Merging logs in file-list", fname_logList ); - m_saveFname = vk_mkstemp( QString( get_VK_LOGS_DIR() ) - + "mc_merged", "xml" ); - vk_assert( !m_saveFname.isEmpty() ); + saveFname = vk_mkstemp( QString( get_VK_LOGS_DIR() ) + + "mc_merged", "xml" ); + vk_assert( !saveFname.isEmpty() ); QStringList flags; flags << vkConfig->rdEntry( "merge-exec","valkyrie"); flags << "-f"; flags << fname_logList; flags << "-o"; - flags << m_saveFname; + flags << saveFname; - setRunState( VkRunState::TOOL2 ); - m_fileSaved = false; + setProcessId( VkRunState::TOOL2 ); + fileSaved = false; statusMsg( "Merge Logs", "Running ... " ); bool ok = startProcess( flags ); if (!ok) { statusMsg( "Merge Logs", "Failed" ); - m_fileSaved = true; - setRunState( VkRunState::STOPPED ); + fileSaved = true; + setProcessId( VkRunState::STOPPED ); } return ok; #endif @@ -557,208 +581,225 @@ */ bool Memcheck::startProcess( QStringList flags ) { + QString program = flags.at( 0 ); + QStringList args = flags.mid(1); + // vkPrint("Memcheck::startProcess()"); - // for ( unsigned int i=0; i<flags.count(); i++ ) - // vkPrint("flag[%d] --> %s", i, flags[i].latin1() ); + for ( int i=0; i<flags.count(); i++ ) + vkPrint("flag[%d] --> %s", i, qPrintable( flags[i] ) ); vk_assert( getToolView() != 0 ); -#if 0 - /* new m_vgreader - view() may be recreated, so need up-to-date ptr */ - vk_assert( m_vgreader == 0 ); - m_vgreader = new VgLogReader( view()->vgLogPtr() ); + // new vgreader - view may have been recreated, so need up-to-date ptr + vk_assert( vgreader == 0 ); + vgreader = new VgLogReader( getToolView()->vgLogPtr() ); - /* start the log parse - nothing written yet tho */ - if (!m_vgreader->parse( m_saveFname, true )) { - QString errMsg = m_vgreader->handler()->fatalMsg(); - VK_DEBUG("m_vgreader failed to start parsing empty log\n"); - vkError( view(), "Process Startup Error", + // start the log parse - nothing written yet tho. + if (!vgreader->parse( saveFname, true )) { + QString errMsg = vgreader->handler()->fatalMsg(); + VK_DEBUG("vgreader failed to start parsing empty log\n"); + vkError( getToolView(), "Process Startup Error", "<p>Failed to start XML parser:<br>%s</p>", - errMsg.ascii() ); + qPrintable( errMsg ) ); goto failed_startup; } - /* start a new process, listening on exit signal */ - vk_assert( m_vgproc == 0 ); - m_vgproc = new VKProcess( flags, this ); - connect( m_vgproc, SIGNAL(processExited()), - this, SLOT(processDone()) ); + // start a new process, listening on exit signal + vk_assert( vgproc == 0 ); + vgproc = new QProcess( this->toolView ); + connect( vgproc, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(processDone(int, QProcess::ExitStatus)) ); - /* don't need to talk/listen to forked process, - so don't let it hijack stdin/out/err for socket fd's */ - m_vgproc->setCommunication( 0 ); + // forward vg process stdout/err to our stdout/err respectively + vgproc->setProcessChannelMode( QProcess::ForwardedChannels ); - /* set working directory */ - m_vgproc->setWorkingDirectory( - QDir( vkConfig->rdEntry( "working-dir", "valkyrie" ) ) ); + // set working directory + vgproc->setWorkingDirectory( vkConfig->value( "valkyrie/working-dir" ).toString() ); - if ( !m_vgproc->start() ) { + // start running process + vgproc->start( program, args ); + +//TODO: call vgproc->waitForStarted(), or sthgn with a timeout, and then error to user... +#if 0 VK_DEBUG("process failed to start"); - QString path_errmsg = (runState() == VkRunState::VALGRIND) - ? "Please verify the path to Valgrind in Options::Valkyrie." - : ""; /* TODO: same for vk_logmerge... and provide option widgets to update path... */ - vkError( view(), "Process Startup Error", - "<p>Failed to start process:<br>%s<br><br>%s</p>", - flags.join(" ").latin1(), - path_errmsg.latin1() ); + vkError( getToolView(), "Process Startup Error", + "<p>Failed to start process:<br>%s<br><br>" + "Please verify the path to Valgrind in Options::Valkyrie.</p>", + qPrintable( flags.join(" ") ) ); goto failed_startup; } +#endif - /* poll log for latest data */ - if (!m_logpoller->start()) { - QString errMsg = m_vgreader->handler()->fatalMsg(); - VK_DEBUG("m_logpoller failed to start\n"); - vkError( view(), "Process Startup Error", - "<p>Failed to start log poller.</p>" ); - goto failed_startup; - } + // poll log for latest data + logpoller->start(); - // vkPrint(" - END MC::startProcess()" ); +vkPrint(" - END MC::startProcess()" ); return true; failed_startup: - VK_DEBUG("failed_startup: '%s'", flags.join(" ").latin1()); - if (m_logpoller != 0) { - m_logpoller->stop(); + VK_DEBUG("failed_startup: '%s'", qPrintable( flags.join(" ") )); + if (logpoller != 0) { + logpoller->stop(); } - if (m_vgreader != 0) { - delete m_vgreader; - m_vgreader = 0; + if (vgreader != 0) { + delete vgreader; + vgreader = 0; } - if (m_vgproc != 0) { - delete m_vgproc; - m_vgproc = 0; + if (vgproc != 0) { + delete vgproc; + vgproc = 0; } return false; -#endif - return true; } -/* Process exited: - - self / external signal / user via 'stop()' / - - terminated from readVgLog because of an xml parse error - Stops logfile polling, checks xml parsing for errors, - checks exitstatus, cleans up. +/*! + Process exited: + - self / external signal / user via 'stop()' / + - terminated from readVgLog because of an xml parse error + Stops logfile polling, checks xml parsing for errors, + checks exitstatus, cleans up. */ -void Memcheck::processDone() +void Memcheck::processDone( int exitCode, QProcess::ExitStatus exitStatus ) { -#if 0 + cerr << "Memcheck::processDone( " << exitCode << ", " << exitStatus << " )" << endl; + // vkPrint("Memcheck::processDone()"); - vk_assert( m_vgproc != 0 ); - vk_assert( m_vgreader != 0 ); - vk_assert( m_logpoller != 0 ); + vk_assert( vgproc != 0 ); + vk_assert( vgreader != 0 ); + vk_assert( logpoller != 0 ); bool runError = false; - /* stop polling logfile ------------------------------------------ */ - m_logpoller->stop(); + // stop polling logfile ------------------------------------------ + logpoller->stop(); - /* deal with log reader ------------------------------------------ */ - /* if not finished && no error, try reading log data one last time */ - if (!m_vgreader->handler()->finished() && - m_vgreader->handler()->fatalMsg().isEmpty()) + // deal with log reader ------------------------------------------ + // if not finished && no error, try reading log data one last time + if (!vgreader->handler()->finished() && + vgreader->handler()->fatalMsg().isEmpty()) readVgLog(); - /* did log parsing go ok? */ - QString fatalMsg = m_vgreader->handler()->fatalMsg(); + // did log parsing go ok? + QString fatalMsg = vgreader->handler()->fatalMsg(); if ( !fatalMsg.isEmpty() ) { - /* fatal log error... */ + // fatal log error... runError = true; // vkPrint(" - Memcheck::processDone(): fatal error"); - if (runState() == VkRunState::VALGRIND) { + if (getProcessId() == TOOL::PROC_VALGRIND) { statusMsg( "Memcheck", "Error parsing output log" ); - vkError( view(), "XML Parse Error", + vkError( getToolView(), "XML Parse Error", "<p>Error parsing Valgrind XML output:<br>%s</p>", - str2html( fatalMsg ).latin1() ); + qPrintable( str2html( fatalMsg ) ) ); } else { + vk_assert_never_reached(); +//TODO. maybe +#if 0 statusMsg( "Merge Logs", "Error parsing output log" ); - vkError( view(), "Parse Error", + vkError( getToolView(), "Parse Error", "<p>Error parsing output log</p>" ); +#endif } - } else if ( !m_vgreader->handler()->finished() ) { + } else if ( !vgreader->handler()->finished() ) { /* no fatal error, but STILL not reached end of log, either: - valgrind xml output not completed properly - merge failed */ runError = true; // vkPrint(" - Memcheck::processDone(): parsing STILL not finished"); - - if (runState() == VkRunState::VALGRIND) { + + if (getProcessId() == TOOL::PROC_VALGRIND) { statusMsg( "Memcheck", "Error - incomplete output log" ); - vkError( view(), "XML Parse Error", + vkError( getToolView(), "XML Parse Error", "<p>Valgrind XML output is incomplete</p>" ); } else { + vk_assert_never_reached(); +//TODO. maybe. +#if 0 statusMsg( "Merge Logs", "Error - incomplete output log" ); - vkError( view(), "Parse Error", + vkError( getToolView(), "Parse Error", "<p>Failed to parse merge result</p>" ); +#endif } - } - /* check process exit status - - valgrind might have bombed ---------------------------------- */ - bool exitStatus = m_vgproc->exitStatus(); - if (exitStatus != 0) { + + // check process exit status - valgrind might have bombed + if ( exitStatus == QProcess::NormalExit && exitCode == 0 ) { + // vkPrint(" - Memcheck::processDone(): process exited ok"); + } else { // vkPrint(" - Memcheck::processDone(): process failed (%d)", exitStatus); - if (runState() == VkRunState::VALGRIND) { - vkError( view(), "Run Error", - "<p>Process exited with return value %d.<br> \ + if (getProcessId() == TOOL::PROC_VALGRIND) { + vkError( getToolView(), "Run Error", + "<p>Process %s, with return value %d.<br> \ This is likely to simply be the client program \ return value. If, however, you suspect Valgrind \ itself may have crashed, please click 'OK', then \ - 'Save Log' and examine for details.</p>", exitStatus); + 'Save Log' and examine for details.</p>", + (exitStatus == QProcess::NormalExit) ? "exited normally" : "crashed", + exitCode ); } else { - vkError( view(), "Parse Error", + vk_assert_never_reached(); +//TODO: maybe. +#if 0 + vkError( getToolView(), "Parse Error", "<p>Merge process exited with return value %d.<br> \ Please check the terminal for error messages.</p>", exitStatus); +#endif } - } else { - // vkPrint(" - Memcheck::processDone(): process exited ok"); } - /* cleanup ------------------------------------------------------- */ - delete m_vgreader; - m_vgreader = 0; - delete m_vgproc; - m_vgproc = 0; + // cleanup ------------------------------------------------------- + delete vgreader; + vgreader = 0; + delete vgproc; + vgproc = 0; - /* we're done. --------------------------------------------------- */ - if (!runError) { /* (else we've already set an status error message) */ - if (runState() == VkRunState::VALGRIND) + // we're done. --------------------------------------------------- + if (!runError) { // (else we've already set an status error message) + if (getProcessId() == TOOL::PROC_VALGRIND) { statusMsg( "Memcheck", "Finished" ); - else - statusMsg( "Merge Logs", "Finished" ); + } else { + vk_assert_never_reached(); +//TODO: maybe +// statusMsg( "Merge Logs", "Finished" ); + } } - setRunState( VkRunState::STOPPED ); +// setProcessId( TOOL::PROC_NONE ); // vkPrint("Memcheck::processDone(): DONE.\n"); -#endif } /* Read memcheck / logmerge xml output Called by - - m_logpoller signals + - logpoller signals - processDone() if one last data read needed. */ void Memcheck::readVgLog() { -#if 0 - // vkPrint("Memcheck::readVgLog()"); - vk_assert( view() != 0 ); - vk_assert( m_vgreader != 0 ); - vk_assert( m_vgproc != 0 ); +vkPrint("Memcheck::readVgLog()"); + vk_assert( getToolView() != 0 ); + vk_assert( vgreader != 0 ); + vk_assert( vgproc != 0 ); qApp->processEvents(); - /* Try reading some more data */ - if ( m_vgreader && !m_vgreader->parseContinue()) { - /* Parsing failed: stop m_vgproc, if running */ - if ( m_vgproc && m_vgproc->isRunning()) - m_vgproc->stop(); /* signal -> processDone() */ + // starting or dead -> get out of here. + if ( vgproc->state() != QProcess::Running ) + return; + + // Try reading some more data. By failure, stop process. + if ( vgreader && !vgreader->parseContinue()) { +vkPrint("Memcheck::readVgLog(): Parsing Failed. Stopping process after timeout"); + + // stop trying to read from the log. + logpoller->stop(); + +//TODO: necessary? + // give process a little time to finishe before we stop it. + QTimer::singleShot( TIMEOUT_STOPPROC, this, SLOT( stop() ) ); } -#endif } @@ -783,7 +824,7 @@ if ( fname.isEmpty() ) { /* Start save-dialog in User-configured default log dir*/ QString start_path = vkConfig->rdEntry( "default-logdir", "valkyrie" ); - fname = dlg.getSaveFileName( start_path, flt, view(), "fsdlg", cptn ); + fname = dlg.getSaveFileName( start_path, flt, getToolView(), "fsdlg", cptn ); if ( fname.isEmpty() ) return false; } @@ -791,7 +832,7 @@ /* try to save file until succeed, or user Cancels */ while ( !saveParsedOutput( fname ) ) { QString start_path = QFileInfo( fname ).dirPath(); - fname = dlg.getSaveFileName( start_path, flt, view(), "fsdlg", cptn ); + fname = dlg.getSaveFileName( start_path, flt, getToolView(), "fsdlg", cptn ); if ( fname.isEmpty() ) /* Cancelled */ return false; } @@ -800,13 +841,13 @@ } /* Save to file - - we already have everything in m_saveFname logfile, so just copy that + - we already have everything in saveFname logfile, so just copy that */ bool Memcheck::saveParsedOutput( QString& fname ) { #if 0 //vkPrint("saveParsedOutput(%s)", fname.latin1() ); - vk_assert( view() != 0 ); + vk_assert( getToolView() != 0 ); vk_assert( !fname.isEmpty() ); /* make sure path is absolute */ @@ -814,7 +855,7 @@ /* if this filename already exists, check if we should over-write it */ if ( QFile::exists( fname ) ) { - int ok = vkQuery( view(), 2, "Overwrite File", + int ok = vkQuery( getToolView(), 2, "Overwrite File", "<p>Over-write existing file '%s' ?</p>", fname.latin1() ); if ( ok == MsgBox::vkNo ) { @@ -825,38 +866,38 @@ /* save log (=copy/rename) */ bool ok; - if (!m_fileSaved) { - /* first save after a run, so just rename m_saveFname => fname */ + if (!fileSaved) { + /* first save after a run, so just rename saveFname => fname */ if (0) vkPrint("renaming: '%s' -> '%s'", - m_saveFname.latin1(), fname.latin1() ); - if (m_saveFname != fname) { - ok = FileCopy( m_saveFname, fname ); + saveFname.latin1(), fname.latin1() ); + if (saveFname != fname) { + ok = FileCopy( saveFname, fname ); if (ok) - ok = QDir().remove( m_saveFname ); + ok = QDir().remove( saveFname ); } else { ok = true; // no need to do anything } // OLD: - //ok = QDir().rename( m_saveFname, fname ); + //ok = QDir().rename( saveFname, fname ); // but we can't just rename, because that fails when the src // and dst files are in different partitions. The longwinded // but more reliable solution is to copy and then delete the // original. } else { - /* we've saved once already: must now copy m_saveFname => fname */ + /* we've saved once already: must now copy saveFname => fname */ if (0) vkPrint("copying: '%s' -> '%s'", - m_saveFname.latin1(), fname.latin1() ); - ok = FileCopy( m_saveFname, fname ); + saveFname.latin1(), fname.latin1() ); + ok = FileCopy( saveFname, fname ); } if (ok) { - m_saveFname = fname; - m_fileSaved = true; - statusMsg( "Saved", m_saveFname ); + saveFname = fname; + fileSaved = true; + statusMsg( "Saved", saveFname ); } else { /* nogo: return and try again */ - vkInfo( view(), "Save Failed", + vkInfo( getToolView(), "Save Failed", "<p>Failed to save file to '%s'", fname.latin1() ); - statusMsg( "Failed Save", m_saveFname ); + statusMsg( "Failed Save", saveFname ); } return ok; #endif Modified: branches/valkyrie_qt4port/objects/memcheck_object.h =================================================================== --- branches/valkyrie_qt4port/objects/memcheck_object.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/memcheck_object.h 2010-01-27 22:54:53 UTC (rev 472) @@ -21,19 +21,17 @@ #ifndef __MEMCHECK_OBJECT_H #define __MEMCHECK_OBJECT_H - #include "objects/tool_object.h" -#include "toolview/memcheckview.h" #include "options/memcheck_options_page.h" +#include "toolview/memcheckview.h" +#include "utils/vglogreader.h" +#include "utils/vk_logpoller.h" -//#include "vk_logpoller.h" -//#include "vglogreader.h" -//#include "vk_process.h" +#include <QProcess> +#include <QStringList> -//TODO - // ============================================================ namespace MEMCHECK { @@ -59,10 +57,9 @@ Tools can run different processes */ enum mcProcessId { - PROC_NOPROC = -1, - PROC_RUN_VALGRIND, - PROC_PARSE_LOGFILE, - NUM_PROCS + PROC_PARSE_LOG = TOOL::PROC_TOOL_NONE+1, + // Any other process id's go here. + PROC_MAX = TOOL::PROC_MAX }; } @@ -85,7 +82,6 @@ bool queryDone(); bool start( int procId, QStringList vgflags ); - void stop(); unsigned int maxOptId() { return MEMCHECK::NUM_OPTS; } @@ -100,6 +96,7 @@ public slots: bool fileSaveDialog( QString fname=QString() ); + void stop(); private: // overriding to avoid casting everywhere @@ -115,16 +112,15 @@ bool startProcess( QStringList flags ); private slots: - void processDone(); + void processDone( int exitCode, QProcess::ExitStatus exitStatus ); void readVgLog(); + void killProcess(); private: -/* - QString m_saveFname; - VgLogReader* m_vgreader; - VKProcess* m_vgproc; - VkLogPoller* m_logpoller; -*/ + QString saveFname; + VgLogReader* vgreader; + QProcess* vgproc; + VkLogPoller* logpoller; }; Modified: branches/valkyrie_qt4port/objects/tool_object.cpp =================================================================== --- branches/valkyrie_qt4port/objects/tool_object.cpp 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/tool_object.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -37,7 +37,7 @@ */ ToolObject::ToolObject( const QString& objectName, VGTOOL::ToolID id ) : VkObject( objectName ), - toolView(0), fileSaved(true), runState(VkRunState::STOPPED), toolId(id) + toolView(0), fileSaved(true), processId(TOOL::PROC_NONE), toolId(id) { } @@ -45,20 +45,41 @@ ToolObject::~ToolObject() {} -#if 0 bool ToolObject::isRunning() { - return (m_runState != VkRunState::STOPPED); + return (processId > TOOL::PROC_NONE); } -void ToolObject::setRunState( VkRunState::State rs ) + +/*! + Set the process id. + Emits signal for subsequent state: 'running(true|false)' +*/ +void ToolObject::setProcessId( int procId ) { - m_runState = rs; + vk_assert( procId >= TOOL::PROC_NONE ); + vk_assert( procId != TOOL::PROC_TOOL_NONE ); + vk_assert( procId < TOOL::PROC_MAX); + + processId = procId; emit running( isRunning() ); } +/*! + get the currently-running process id +*/ +int ToolObject::getProcessId() +{ + vk_assert( processId >= TOOL::PROC_NONE ); + vk_assert( processId != TOOL::PROC_TOOL_NONE ); + vk_assert( processId < TOOL::PROC_MAX ); + return processId; +} + + +#if 0 void ToolObject::deleteView() { emit message( "" ); /* clear the status bar */ Modified: branches/valkyrie_qt4port/objects/tool_object.h =================================================================== --- branches/valkyrie_qt4port/objects/tool_object.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/tool_object.h 2010-01-27 22:54:53 UTC (rev 472) @@ -34,13 +34,15 @@ #include <QList> -/* Own namespace for ease of use */ -namespace VkRunState { - /* STOPPED: no process running - * VALGRIND: running valgrind - * TOOL*: running a tool-defined process - */ - enum State { STOPPED=-1, VALGRIND=0, TOOL1, TOOL2, TOOL3 }; +namespace TOOL { + // Tools may extend this enum with their own process id's. + enum toolProcessId { + PROC_NONE=-1, // no process running + PROC_VALGRIND=0, // run valgrind for given tool + PROC_TOOL_NONE=1, // tool defined proc id's start here + 1 + // tool defined processes may take up this block + PROC_MAX=4 // reasonable number of processes per tool + }; } @@ -76,27 +78,26 @@ // stop a process: doesn't exit until success virtual void stop() = 0; -/* bool isRunning(); +/* virtual OptionsPage* createOptionsPage( OptionsWindow* parent ) = 0; // returns a list of non-default flags to pass to valgrind virtual QStringList modifiedVgFlags(); +*/ signals: void running( bool ); void message( QString ); - void fatal(); +//TODO: needed? +// void fatal(); protected: - // set runstate and emit signal running(bool) - void setRunState( VkRunState::State ); - // get runstate - VkRunState::State runState() { return runState; } + void setProcessId( int procId ); + int getProcessId(); virtual bool runValgrind( QStringList vgflags ) = 0; -*/ public: VGTOOL::ToolID getToolId() { return toolId; } @@ -106,8 +107,8 @@ bool fileSaved; private: - // Keep track of current running state - VkRunState::State runState; + // tools need to add own processId's: classic enum extend problem :-( + int processId; VGTOOL::ToolID toolId; // which tool are we. }; Modified: branches/valkyrie_qt4port/objects/valkyrie_object.cpp =================================================================== --- branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/valkyrie_object.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -19,6 +19,7 @@ ****************************************************************************/ #include "help/help_urls.h" +#include "objects/tool_object.h" #include "objects/valkyrie_object.h" #include "options/valkyrie_options_page.h" // createVkOptionsPage() #include "utils/vk_config.h" @@ -614,7 +615,7 @@ /*! - Run the tool with given runState + Run the tool with given process id. */ bool Valkyrie::runTool( VGTOOL::ToolID tId, int procId ) { @@ -624,9 +625,36 @@ ToolObject* activeTool = valgrind()->getToolObj( tId ); vk_assert( activeTool != 0 ); - return activeTool->start( procId, QStringList() ); -//TODO -// return activeTool->start( procId, m_flags ); + return activeTool->start( procId, vg_flags ); } +/*! + Update flags for current tool + Called by MainWindow::updateVgFlags() + - which is triggered by optionsWin::flagsChanged signal +*/ +void Valkyrie::updateVgFlags( VGTOOL::ToolID tId ) +{ +cerr << "Valkyrie::updateVgFlags( " << tId << ")" << endl; + + vk_assert( tId != VGTOOL::ID_NULL ); + ToolObject* tool = valgrind()->getToolObj( tId ); + vk_assert( tool != 0 ); + + QString vg_exec = vkConfig->value( "valkyrie/vg-exec" ).toString(); + if (vg_exec.isEmpty()) + vg_exec = "valgrind"; // hope it's in $PATH + + // modifiedVgFlags() functions return non-default flags + vg_flags.clear(); + vg_flags << vg_exec; // path/to/valgrind + vg_flags << "--tool=" + tool->objectName(); // tool + +//TODO: + vg_flags << "ls"; +// vg_flags += valgrind()->modifiedVgFlags( tool ); // valgrind opts +// vg_flags += tool->modifiedVgFlags(); // tool opts +// vg_flags += this->modifiedVgFlags(); // valkyrie opts +} + Modified: branches/valkyrie_qt4port/objects/valkyrie_object.h =================================================================== --- branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/objects/valkyrie_object.h 2010-01-27 22:54:53 UTC (rev 472) @@ -69,6 +69,8 @@ #if 0 // TODO bool queryToolDone( int tId ); #endif + void updateVgFlags( VGTOOL::ToolID tId ); + unsigned int maxOptId() { return VALKYRIE::NUM_OPTS; } int checkOptArg( QString optGrp, int optid, QString& argval ); @@ -97,6 +99,7 @@ private: Valgrind* m_valgrind; + QStringList vg_flags; }; Modified: branches/valkyrie_qt4port/toolview/vglogview.cpp =================================================================== --- branches/valkyrie_qt4port/toolview/vglogview.cpp 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/toolview/vglogview.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -21,7 +21,6 @@ #include "toolview/vglogview.h" #include "utils/vk_utils.h" #include "utils/vk_config.h" -//#include "vglogview_icons.h" #include <QFileInfo> #include <QStringList> @@ -829,8 +828,8 @@ /*! VgLogView: inherits VgLog */ -VgLogView::VgLogView( QTreeWidget* lv ) - : lview(lv), lastChild( 0 ) +VgLogView::VgLogView( QTreeWidget* v ) + : view(v), lastChild( 0 ) { } VgLogView::~VgLogView() @@ -857,7 +856,7 @@ if (state == VgStatus::RUNNING) { VgElement exe = args().getFirstElem( "argv" ).getFirstElem( "exe" ); - topStatus = new TopStatusItem( lview, status, exe, protocol().text() ); + topStatus = new TopStatusItem( view, status, exe, protocol().text() ); topStatus->setOpen( true ); lastChild = new InfoItem( topStatus, docroot() ); lastChild = new PreambleItem( topStatus, lastChild, preamble() ); Modified: branches/valkyrie_qt4port/toolview/vglogview.h =================================================================== --- branches/valkyrie_qt4port/toolview/vglogview.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/toolview/vglogview.h 2010-01-27 22:54:53 UTC (rev 472) @@ -221,7 +221,7 @@ class VgLogView : public VgLog { public: - VgLogView( QTreeWidget* lv ); + VgLogView( QTreeWidget* ); ~VgLogView(); bool appendNode( QDomNode node ); @@ -230,7 +230,7 @@ void updateErrorItems( VgErrCounts ec ); private: - QTreeWidget* lview; // we don't own this: don't delete it + QTreeWidget* view; // we don't own this: don't delete it VgOutputItem* lastChild; TopStatusItem* topStatus; }; Copied: branches/valkyrie_qt4port/utils/vk_logpoller.cpp (from rev 471, trunk/valkyrie/tool_utils/vk_logpoller.cpp) =================================================================== --- branches/valkyrie_qt4port/utils/vk_logpoller.cpp (rev 0) +++ branches/valkyrie_qt4port/utils/vk_logpoller.cpp 2010-01-27 22:54:53 UTC (rev 472) @@ -0,0 +1,59 @@ +/**************************************************************************** +** VkLogPoller implementation +** - polls a log for updates +** -------------------------------------------------------------------------- +** +** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved. +** <in...@op...> +** +** This file is part of Valkyrie, a front-end for Valgrind. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file COPYING included in the packaging of +** this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "utils/vk_logpoller.h" + + +VkLogPoller::VkLogPoller ( QObject* parent, const char* name ) + : QObject( parent ) +{ + this->setObjectName( name ); + + timer = new QTimer( this ); + + connect( timer, SIGNAL(timeout()), + this, SIGNAL(logUpdated()) ); +} + + +VkLogPoller::~VkLogPoller() +{ + // timer deleted by it's parent: this +} + + +void VkLogPoller::start( int interval ) +{ + timer->start( interval ); +} + + +void VkLogPoller::stop() +{ + if (timer->isActive()) + timer->stop(); +} + + +bool VkLogPoller::isActive() +{ + return timer->isActive(); +} + Copied: branches/valkyrie_qt4port/utils/vk_logpoller.h (from rev 471, trunk/valkyrie/tool_utils/vk_logpoller.h) =================================================================== --- branches/valkyrie_qt4port/utils/vk_logpoller.h (rev 0) +++ branches/valkyrie_qt4port/utils/vk_logpoller.h 2010-01-27 22:54:53 UTC (rev 472) @@ -0,0 +1,58 @@ +/**************************************************************************** +** VkLogPoller definition +** - polls a log for updates +** -------------------------------------------------------------------------- +** +** Copyright (C) 2000-2010, OpenWorks LLP. All rights reserved. +** <in...@op...> +** +** This file is part of Valkyrie, a front-end for Valgrind. +** +** This file may be used under the terms of the GNU General Public +** License version 2.0 as published by the Free Software Foundation +** and appearing in the file COPYING included in the packaging of +** this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef VK_LOGPOLLER_H +#define VK_LOGPOLLER_H + +#include <QObject> +#include <QTimer> + + +/*! + NOTE: + Future intention is to have another thread running select on the + given file, so triggering signal when the file is updated. + Or something... +*/ + +// ============================================================ +/*! + class VkLogPoller +*/ +class VkLogPoller : public QObject +{ + Q_OBJECT +public: + VkLogPoller( QObject * parent, const char * name ); + ~VkLogPoller(); + + void start( int interval=100 ); + void stop(); + bool isActive(); + int interval(); + +signals: + void logUpdated(); + +private: + QTimer* timer; +}; + +#endif // VK_LOGPOLLER_H Modified: branches/valkyrie_qt4port/utils/vk_utils.h =================================================================== --- branches/valkyrie_qt4port/utils/vk_utils.h 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/utils/vk_utils.h 2010-01-27 22:54:53 UTC (rev 472) @@ -73,11 +73,10 @@ #if DEBUG_ON /* print debugging msg with file+line info to stderr ------------------- */ -# define VK_DEBUG(msg, args...) { \ - vkPrintErr("DEBUG: %s#%d:%s:", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__ ); \ - vkPrintErr(msg, ## args ); \ - vkPrintErr(" "); \ +# define VK_DEBUG(msg, args...) { \ + vkPrintErr("DEBUG: %s#%d:%s:", __FILE__, __LINE__, __PRETTY_FUNCTION__ ); \ + vkPrintErr(msg, ## args ); \ + vkPrintErr(" "); \ } #else # define VK_DEBUG(msg, args...) /*NOTHING*/ Modified: branches/valkyrie_qt4port/valkyrie.pro =================================================================== --- branches/valkyrie_qt4port/valkyrie.pro 2010-01-24 18:57:15 UTC (rev 471) +++ branches/valkyrie_qt4port/valkyrie.pro 2010-01-27 22:54:53 UTC (rev 472) @@ -37,6 +37,7 @@ utils/vglog.cpp \ utils/vglogreader.cpp \ utils/vk_config.cpp \ + utils/vk_logpoller.cpp \ utils/vk_messages.cpp \ utils/vk_utils.cpp HEADERS += mainwindow.h \ @@ -72,6 +73,7 @@ utils/vglog.h \ utils/vglogreader.h \ utils/vk_config.h \ + utils/vk_logpoller.h \ utils/vk_messages.h \ utils/vk_utils.h RESOURCES += icons.qrc |