📄 memcheck_object.cpp
字号:
{ vk_assert( view() != 0 ); QString log_file = vkConfig->rdEntry( "view-log", "valkyrie" ); statusMsg( "Parsing", log_file ); /* check this is a valid file, and has the right perms */ int errval = PARSED_OK; QString ret_file = fileCheck( &errval, log_file, true, false ); if ( errval != PARSED_OK ) { vkError( view(), "File Error", "%s: \n\"%s\"", parseErrString(errval), escapeEntities(log_file).latin1() ); return false; } log_file = ret_file; /* fileSaved is always true here 'cos we are just parsing a file which already exists on disk */ m_fileSaved = true; setRunState( VkRunState::TOOL1 ); /* Could be a very large file, so at least get ui up-to-date now */ qApp->processEvents( 1000/*max msecs*/ ); /* Parse the log */ VgLogReader vgLogFileReader( view()->vgLogPtr() ); bool success = vgLogFileReader.parse( log_file ); if (!success) { VgLogHandler* hnd = vgLogFileReader.handler(); statusMsg( "Parsing", "Error" ); vkError( view(), "XML Parse Error", "<p>%s</p>", escapeEntities(hnd->fatalMsg()).latin1() ); } if (success) { m_saveFname = log_file; statusMsg( "Loaded", log_file ); } else { statusMsg( "Parse failed", log_file ); } setRunState( VkRunState::STOPPED ); return success;}/* if --merge=<file_list> was specified on the cmd-line, called by valkyrie->runTool(); if set via the open-file-dialog in the gui, called by MemcheckView::openMergeFile(). either way, the value in [valkyrie:merge] is what we need to know */bool Memcheck::mergeLogFiles(){ QString fname_logList = vkConfig->rdEntry( "merge", "valkyrie" ); statusMsg( "Merging logs in file-list", fname_logList ); m_saveFname = vk_mkstemp( vkConfig->logsDir() + "mc_merged", "xml" ); vk_assert( !m_saveFname.isEmpty() ); QStringList flags; flags << vkConfig->rdEntry( "merge-exec","valkyrie"); flags << "-f"; flags << fname_logList; flags << "-o"; flags << m_saveFname; setRunState( VkRunState::TOOL2 ); m_fileSaved = false; statusMsg( "Merge Logs", "Running ... " ); bool ok = startProcess( flags ); if (!ok) { statusMsg( "Merge Logs", "Failed" ); m_fileSaved = true; setRunState( VkRunState::STOPPED ); } return ok;}/* Run a VKProcess, as given by 'flags'. Reads ouput from file, loading this to the listview.*/bool Memcheck::startProcess( QStringList flags ){ // vkPrint("Memcheck::startProcess()"); // for ( unsigned int i=0; i<flags.count(); i++ ) // vkPrint("flag[%d] --> %s", i, flags[i].latin1() ); vk_assert( view() != 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() ); /* 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", "<p>Failed to start XML parser:<br>%s</p>", errMsg.ascii() ); 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()) ); /* 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 ); if ( !m_vgproc->start() ) { 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() ); goto failed_startup; } /* 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; } // vkPrint(" - END MC::startProcess()" ); return true; failed_startup: VK_DEBUG("failed_startup: '%s'", flags.join(" ").latin1()); if (m_logpoller != 0) { m_logpoller->stop(); } if (m_vgreader != 0) { delete m_vgreader; m_vgreader = 0; } if (m_vgproc != 0) { delete m_vgproc; m_vgproc = 0; } return false;}/* 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(){ // vkPrint("Memcheck::processDone()"); vk_assert( m_vgproc != 0 ); vk_assert( m_vgreader != 0 ); vk_assert( m_logpoller != 0 ); bool runError = false; /* stop polling logfile ------------------------------------------ */ m_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()) readVgLog(); /* did log parsing go ok? */ QString fatalMsg = m_vgreader->handler()->fatalMsg(); if ( !fatalMsg.isEmpty() ) { /* fatal log error... */ runError = true; // vkPrint(" - Memcheck::processDone(): fatal error"); if (runState() == VkRunState::VALGRIND) { statusMsg( "Memcheck", "Error parsing output log" ); vkError( view(), "XML Parse Error", "<p>Error parsing Valgrind XML output:<br>%s</p>", str2html( fatalMsg ).latin1() ); } else { statusMsg( "Merge Logs", "Error parsing output log" ); vkError( view(), "Parse Error", "<p>Error parsing output log</p>" ); } } else if ( !m_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) { statusMsg( "Memcheck", "Error - incomplete output log" ); vkError( view(), "XML Parse Error", "<p>Valgrind XML output is incomplete</p>" ); } else { statusMsg( "Merge Logs", "Error - incomplete output log" ); vkError( view(), "Parse Error", "<p>Failed to parse merge result</p>" ); } } /* check process exit status - valgrind might have bombed ---------------------------------- */ bool exitStatus = m_vgproc->exitStatus(); if (exitStatus != 0) { // vkPrint(" - Memcheck::processDone(): process failed (%d)", exitStatus); if (runState() == VkRunState::VALGRIND) { vkError( view(), "Run Error", "<p>Process exited 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 'Save Log' and \ examine for details.</p>", exitStatus); } else { vkError( view(), "Parse Error", "<p>Merge process exited with return value %d.<br> \ Please check the terminal for error messages.</p>", exitStatus); } } else { // vkPrint(" - Memcheck::processDone(): process exited ok"); } /* cleanup ------------------------------------------------------- */ delete m_vgreader; m_vgreader = 0; delete m_vgproc; m_vgproc = 0; /* we're done. --------------------------------------------------- */ if (!runError) { /* (else we've already set an status error message) */ if (runState() == VkRunState::VALGRIND) statusMsg( "Memcheck", "Finished" ); else statusMsg( "Merge Logs", "Finished" ); } setRunState( VkRunState::STOPPED ); // vkPrint("Memcheck::processDone(): DONE.\n");}/* Read memcheck / logmerge xml output Called by - m_logpoller signals - processDone() if one last data read needed.*/void Memcheck::readVgLog(){ // vkPrint("Memcheck::readVgLog()"); vk_assert( view() != 0 ); vk_assert( m_vgreader != 0 ); vk_assert( m_vgproc != 0 ); qApp->processEvents(); /* Try reading some more data */ if ( !m_vgreader->parseContinue()) { /* Parsing failed: stop m_vgproc, if running */ if (m_vgproc->isRunning()) m_vgproc->stop(); /* signal -> processDone() */ }}/* brings up a fileSaveDialog until successfully saved, or user pressed Cancel. if fname.isEmpty, ask user for a name first. returns false on user pressing Cancel, else true.*/bool Memcheck::fileSaveDialog( QString fname/*=QString()*/ ){ vk_assert( view() != 0 ); QFileDialog dlg; dlg.setShowHiddenFiles( true ); QString flt = "XML Files (*.xml);;Log Files (*.log.*);;All Files (*)"; QString cptn = "Save Log File As"; /* Ask fname if don't have one already */ if ( fname.isEmpty() ) { /* start dlg in dir of last saved logfile */ QString start_path = QFileInfo( m_saveFname ).dirPath(); fname = dlg.getSaveFileName( start_path, flt, view(), "fsdlg", cptn ); if ( fname.isEmpty() ) return false; } /* 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 ); if ( fname.isEmpty() ) /* Cancelled */ return false; } return true;}/* Save to file - we already have everything in m_saveFname logfile, so just copy that*/bool Memcheck::saveParsedOutput( QString& fname ){ //vkPrint("saveParsedOutput(%s)", fname.latin1() ); vk_assert( view() != 0 ); vk_assert( !fname.isEmpty() ); /* make sure path is absolute */ fname = QFileInfo( fname ).absFilePath(); /* if this filename already exists, check if we should over-write it */ if ( QFile::exists( fname ) ) { int ok = vkQuery( view(), 2, "Overwrite File", "<p>Over-write existing file '%s' ?</p>", fname.latin1() ); if ( ok == MsgBox::vkNo ) { /* nogo: return and try again */ return false; } } /* save log (=copy/rename) */ bool ok; if (!m_fileSaved) { /* first save after a run, so just rename m_saveFname => fname */ //vkPrint("renaming: '%s' -> '%s'", m_saveFname.latin1(), fname.latin1() ); ok = QDir().rename( m_saveFname, fname ); } else { /* we've saved once already: must now copy m_saveFname => fname */ //vkPrint("copying: '%s' -> '%s'", m_saveFname.latin1(), fname.latin1() ); ok = FileCopy( m_saveFname, fname ); } if (ok) { m_saveFname = fname; m_fileSaved = true; statusMsg( "Saved", m_saveFname ); } else { /* nogo: return and try again */ vkInfo( view(), "Save Failed", "<p>Failed to save file to '%s'", fname.latin1() ); statusMsg( "Failed Save", m_saveFname ); } return ok;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -