|
From: <sv...@va...> - 2009-10-08 19:24:00
|
Author: cerion
Date: 2009-10-08 20:23:37 +0100 (Thu, 08 Oct 2009)
New Revision: 458
Log:
REVIEW THIS! Long non-commited changes, needs good review
Modified:
branches/exec_start/src/core/memcheck_object.cpp
branches/exec_start/src/core/memcheck_object.h
branches/exec_start/src/core/tool_object.cpp
branches/exec_start/src/core/tool_object.h
branches/exec_start/src/core/valgrind_object.cpp
Modified: branches/exec_start/src/core/memcheck_object.cpp
===================================================================
--- branches/exec_start/src/core/memcheck_object.cpp 2009-02-21 11:03:47 UTC (rev 457)
+++ branches/exec_start/src/core/memcheck_object.cpp 2009-10-08 19:23:37 UTC (rev 458)
@@ -8,6 +8,10 @@
* See the file LICENSE.GPL for the full license details.
*/
+#include <sys/types.h> // fork
+#include <unistd.h> // fork, exec
+#include <string.h> // strcpy
+
#include "memcheck_object.h"
#include "valkyrie_object.h"
#include "vk_config.h"
@@ -245,10 +249,7 @@
break;
case Valkyrie::modeParseOutput:
- proc->tryTerminate(); /* first ask nicely. */
- /* if proc still running after msec_timeout, terminate with prejudice */
- QTimer::singleShot( 2000, proc, SLOT( kill() ) ); // TODO: move N to config
-
+ killProc();
// TODO?: if kill proc while we're i parseOutput(), we could get a segfault?
break;
@@ -401,21 +402,6 @@
}
-/* 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(). */
-bool Memcheck::run( QStringList flags )
-{
- /* tell valkyrie what we are doing */
- emit setRunMode( Valkyrie::modeParseOutput );
-
- /* Read from log_fd */
- int log_fd = vkConfig->rdInt( "log-fd", "valgrind" );
-
- return runProcess( flags, log_fd, "mc_output" );
-}
-
-
/* Run a VKProcess, as given by 'flags'.
Listens to output on 'log_fd', loading this output to the toolView
via xmlParser::loadItem(XmlOutput*).
@@ -590,6 +576,184 @@
emitRunning( false );
}
+
+
+
+
+
+
+
+/* Can't call a member function directly, so go around the houses */
+void glbl_valgrind_handler( int vg_signum )
+{
+ // fprintf(stderr, "glbl_valgrind_handler(%d)\n", vg_signum);
+ Memcheck* mc = (Memcheck*)vkConfig->vkObject( "memcheck" );
+ mc->valgrind_handler( vg_signum );
+}
+
+/* set valgrindExited, so parseLogFileLive can quit on this */
+void Memcheck::valgrind_handler( int vg_signum )
+{
+ /* We got a SIGCHLD
+ for now, assuming child is ready to terminate
+ TODO: deal with child SIGSTOP'ed etc
+ */
+
+ fprintf(stderr, "valgrind_handler(%d)\n", vg_signum);
+ valgrindExited = true;
+}
+
+void Memcheck::parseLogFileLive( QString& logFname )
+{
+ QFile logFile(logFname);
+
+ if ( !logFile.open( IO_ReadOnly ) ) {
+ fprintf(stderr, "err opening file for reading");
+ return;
+ }
+
+ setupParser( true );
+
+ if ( !reader.parse( &source, true ) ) {
+ /* if we get here, it means either:
+ a) Output from valgrind run is bad
+ b) Output from vk_logmerge run is bad
+ - neither should happen, so die.
+ Not very nice, but output-to-date is saved in the auto-log file.
+ TODO: do sthng nicer here - but rem not to block this function!
+ */
+ vk_assert_never_reached();
+ }
+
+ QTextStream stream( &logFile );
+ while ( true ) {
+ QString line;
+ while ( !stream.atEnd() ) {
+ line = stream.readLine(); /* line of text excluding '\n' */
+
+ if (line.isNull()) /* last line for now... */
+ break;
+
+#if 0//DEBUG_ON
+ fprintf(stderr, "V: %s\n", line.latin1());
+#endif
+
+ // Forward line to xmlparser
+ source.setData( line );
+ bool ok = reader.parseContinue();
+ if ( !ok ) {
+ fprintf(stderr, "\nMemcheck::parseLogFileLive(%s): '%s'\n",
+ logFname.latin1(), line.latin1() );
+ /* if we get here, it means either:
+ a) Output from valgrind run is bad
+ b) Output from vk_logmerge run is bad
+ - neither should happen, so die.
+ Not very nice, but output-to-date is saved in the auto-log file.
+ TODO: do sthng nicer here - but rem not to block this function!
+ */
+ vk_assert_never_reached();
+ }
+
+ if (line == "</valgrindoutput>")
+ break;
+ } /* while ( !stream.atEnd ) */
+
+ /* SIGCHLD will reset this when valgrind done: */
+ if (valgrindExited) {
+#if 0//DEBUG_ON
+ fprintf(stderr, "Memcheck::parseLogFileLive(): valgrind finished\n");
+#endif
+ break;
+ }
+ /* or we might have found the last line already: */
+ if (line == "</valgrindoutput>") {
+ break;
+ }
+
+ /* so gui still lives (and stop button works!) */
+ qApp->processEvents();
+
+ int millisec = 100;
+ usleep(millisec * 1000); // microseconds
+ } /* while (true) */
+
+ logFile.close();
+ setupParser( false );
+}
+
+
+/* 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(). */
+bool Memcheck::run( QStringList flags )
+{
+ /* tell valkyrie what we are doing */
+ emit setRunMode( Valkyrie::modeParseOutput );
+
+ /* TODO: scan flags for --log- options, and set logFname accordingly */
+ QString logFname = vk_mkstemp( "mc_output", vkConfig->logsDir(), ".xml" );
+ QString logOpt = "--log-file-exactly=" + logFname;
+ flags.insert( flags.at(1), logOpt );
+
+ char* valg_argv[flags.count()+1];
+ unsigned int i;
+ for ( i=0; i<flags.count(); i++ ) {
+ valg_argv[i] = new char[flags[i].length() + 1];
+ strcpy(valg_argv[i], flags[i].latin1());
+ }
+ valg_argv[i] = NULL;
+
+ /* fork */
+ int pid = fork();
+ if (pid < 0) {
+ vkError( this->view(), "Error", "<p>fork() failed:<br>%s</p>",
+ strerror(errno) );
+ return false;
+ }
+
+ if (pid == 0) {
+ /* child */
+
+ /* new valgrind process */
+ execvp( flags[0].latin1(), valg_argv );
+
+ /* shouldn't reach here */
+ vkError( this->view(), "Error", "<p>execvp failed on: <br>%s<br>%s</p>",
+ flags.join(" ").latin1(), strerror(errno) );
+ return false;
+ }
+
+ fileSaved = false;
+ emitRunning( true );
+ valgrindExited = false;
+ saveFname = logFname;
+
+ /* parent */
+ valg_pid = pid; /* keep track of pid, so can control later */
+
+ /* we need to know when valgrind has finished. */
+ signal(SIGCHLD, glbl_valgrind_handler );
+
+ /* go read the log, real-time */
+ parseLogFileLive( logFname );
+
+ /* clean up valg_argv[] */
+ for ( i=1; i<flags.count(); i++ ) {
+ delete valg_argv[i];
+ }
+
+ /* kill child, if alive */
+ // killProc();
+
+ emitRunning( false );
+ return true;
+}
+
+
+
+
+
+
/* brings up a fileSaveDialog until successfully saved,
or user pressed Cancel.
if fname.isEmpty, ask user for a name first.
Modified: branches/exec_start/src/core/memcheck_object.h
===================================================================
--- branches/exec_start/src/core/memcheck_object.h 2009-02-21 11:03:47 UTC (rev 457)
+++ branches/exec_start/src/core/memcheck_object.h 2009-10-08 19:23:37 UTC (rev 458)
@@ -63,6 +63,8 @@
bool fileSaveDialog( QString fname );
+ void valgrind_handler( int vg_signum );
+
public slots:
void loadClientOutput( const QString&, int log_fd=-1 );
@@ -89,6 +91,8 @@
bool runProcess( QStringList flags, int log_fd, QString fbasename );
+ void parseLogFileLive( QString& logFname );
+
private:
XMLParser* xmlParser;
QXmlSimpleReader reader;
Modified: branches/exec_start/src/core/tool_object.cpp
===================================================================
--- branches/exec_start/src/core/tool_object.cpp 2009-02-21 11:03:47 UTC (rev 457)
+++ branches/exec_start/src/core/tool_object.cpp 2009-10-08 19:23:37 UTC (rev 458)
@@ -12,6 +12,9 @@
* See the file LICENSE.GPL for the full license details.
*/
+#include <sys/types.h> /* waitpid */
+#include <sys/wait.h> /* waitpid */
+
#include "tool_object.h"
#include "tool_view.h"
#include "vk_config.h"
@@ -32,6 +35,8 @@
{
m_view = 0;
proc = 0;
+ valgrindExited = false;
+ valg_pid = 0;
is_Running = false;
fileSaved = true;
@@ -44,9 +49,20 @@
/* kill proc if it is running */
void ToolObject::killProc()
{
+ if (valg_pid > 0) { // valid pid?
+ if (kill( valg_pid, SIGKILL ) == -1) {
+ perror("ToolObject::killProc()");
+ return;
+ }
+
+ /* TODO: sthng with SIGALRM to wait 2 secs, then kill(SIGKILL) */
+
+ valgrindExited = true;
+ valg_pid = 0;
+ }
+
if ( proc != 0 ) {
if ( proc->isRunning() ) {
- /* if this view is closed, don't leave the process running */
proc->tryTerminate();
QTimer::singleShot( 5000, proc, SLOT( kill() ) );
}
Modified: branches/exec_start/src/core/tool_object.h
===================================================================
--- branches/exec_start/src/core/tool_object.h 2009-02-21 11:03:47 UTC (rev 457)
+++ branches/exec_start/src/core/tool_object.h 2009-10-08 19:23:37 UTC (rev 458)
@@ -74,6 +74,9 @@
bool fileSaved;
VKProcess* proc;
+
+ bool valgrindExited;
+ int valg_pid; /* pid of valgrind process */
};
Modified: branches/exec_start/src/core/valgrind_object.cpp
===================================================================
--- branches/exec_start/src/core/valgrind_object.cpp 2009-02-21 11:03:47 UTC (rev 457)
+++ branches/exec_start/src/core/valgrind_object.cpp 2009-10-08 19:23:37 UTC (rev 458)
@@ -329,9 +329,10 @@
}
} break;
- case LOG_PID: /* log to <file>.pid<pid> */
- case LOG_FILE: /* log to <file> */
+// case LOG_PID: /* log to <file>.pid<pid> */
+// case LOG_FILE: /* log to <file> */
case LOG_SOCKET: /* log to socket ipaddr:port */
+ case LOG_FD: /* log to file descriptor */
break;
case XML_OUTPUT: /* the sine qua non */
|