3f66f6a5b3
This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
237 lines
6.7 KiB
C++
237 lines
6.7 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: execmon.cpp
|
|
// Purpose: A simple execution monitor to test if wx samples crash at startup or not
|
|
// Author: Francesco Montorsi
|
|
// Modified by:
|
|
// Created: 25/3/09
|
|
// Copyright: (c) 2009 Francesco Montorsi
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/app.h"
|
|
#include "wx/log.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/cmdline.h"
|
|
#include "wx/vector.h"
|
|
#include "wx/process.h"
|
|
#include "wx/sstream.h"
|
|
#include "wx/utils.h"
|
|
#include "wx/filename.h"
|
|
#include "wx/app.h"
|
|
#include "wx/log.h"
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// utility classes
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class MonitoredProcess : public wxProcess
|
|
{
|
|
public:
|
|
MonitoredProcess()
|
|
{ Redirect(); m_crashed=false; m_exitCode=0; }
|
|
|
|
void OnTerminate(int WXUNUSED(pid), int status)
|
|
{
|
|
wxStringOutputStream out, err;
|
|
if (GetInputStream()) out.Write(*GetInputStream());
|
|
if (GetErrorStream()) err.Write(*GetErrorStream());
|
|
|
|
//wxPrintf("%s\n", stdout.GetString());
|
|
//wxPrintf("%s\n", stderr.GetString());
|
|
|
|
// when wx programs assert on wxGTK/wxMac, they put on stderr a message like:
|
|
// [Debug] date somefilename.pp(nnnn): assert "xxxxx" failed in yyyy
|
|
// but then the assert dialog pop-ups and thus the app doesn't exit
|
|
// FIXME: make assertion detection work also under other platforms
|
|
// see http://trac.wxwidgets.org/ticket/10697
|
|
m_crashed = out.GetString().Contains("assert") ||
|
|
err.GetString().Contains("assert");
|
|
m_exitCode = status;
|
|
}
|
|
|
|
void Kill()
|
|
{
|
|
wxProcess::Kill(GetPid());
|
|
|
|
// wxProcess::Kill doesn't trigger a call to OnTerminate() normally...
|
|
// but we still need to call it!
|
|
OnTerminate(0, -1);
|
|
}
|
|
|
|
bool Crashed() const
|
|
{ return m_crashed; }
|
|
|
|
int GetExitCode() const
|
|
{ return m_exitCode; }
|
|
|
|
private:
|
|
bool m_crashed;
|
|
int m_exitCode;
|
|
};
|
|
|
|
class MonitorData
|
|
{
|
|
public:
|
|
MonitorData(const wxString& cmd) : program(cmd) {}
|
|
|
|
wxString program;
|
|
MonitoredProcess process;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// the real main
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool TestExec(const wxVector<wxFileName>& programs, long timeout)
|
|
{
|
|
size_t i;
|
|
wxVector<MonitorData*> data;
|
|
|
|
// run all programs specified as command line parameters
|
|
wxArrayLong procID;
|
|
for (i=0; i<programs.size(); i++)
|
|
{
|
|
MonitorData *dt = new MonitorData(programs[i].GetFullPath());
|
|
|
|
long pid = wxExecute(programs[i].GetFullPath(), wxEXEC_ASYNC, &dt->process);
|
|
if (pid == 0)
|
|
{
|
|
wxLogError("could not run the program '%s'", programs[i].GetFullPath());
|
|
}
|
|
else
|
|
{
|
|
wxLogMessage("started program '%s' (pid %d)...",
|
|
programs[i].GetFullPath(), pid);
|
|
wxASSERT(dt->process.GetPid() == pid);
|
|
|
|
data.push_back(dt);
|
|
}
|
|
}
|
|
|
|
// sleep some moments
|
|
wxSleep(timeout);
|
|
|
|
// check if all processes are still running
|
|
bool allok = true;
|
|
for (i=0; i<data.size(); i++)
|
|
{
|
|
MonitoredProcess& proc = data[i]->process;
|
|
const wxString& prog = data[i]->program;
|
|
|
|
if (wxProcess::Exists(proc.GetPid()))
|
|
proc.Kill();
|
|
else
|
|
{
|
|
// this typically never happens, at least when running wx-programs
|
|
// built with debug builds of wx (see MonitoredProcess::OnTerminate;
|
|
// even if an asserts fail the app doesn't automatically close!):
|
|
|
|
wxLogMessage("program '%s' (pid %d) is NOT running anymore...",
|
|
prog, proc.GetPid());
|
|
allok = false;
|
|
}
|
|
|
|
if (data[i]->process.Crashed())
|
|
{
|
|
allok = false;
|
|
wxLogMessage("program '%s' (pid %d) crashed...",
|
|
prog, proc.GetPid());
|
|
}
|
|
else
|
|
wxLogMessage("program '%s' (pid %d) ended with exit code %d...",
|
|
prog, proc.GetPid(), proc.GetExitCode());
|
|
}
|
|
|
|
return allok;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// main
|
|
// ----------------------------------------------------------------------------
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "execmon");
|
|
|
|
wxInitializer initializer;
|
|
if ( !initializer )
|
|
{
|
|
fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
|
|
return -1;
|
|
}
|
|
|
|
static const wxCmdLineEntryDesc cmdLineDesc[] =
|
|
{
|
|
{ wxCMD_LINE_SWITCH, "h", "help",
|
|
"show this help message",
|
|
wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
|
|
{ wxCMD_LINE_OPTION, "t", "timeout",
|
|
"kills all processes still alive after 'num' seconds",
|
|
wxCMD_LINE_VAL_NUMBER, 0 },
|
|
{ wxCMD_LINE_PARAM, "", "",
|
|
"program-to-run",
|
|
wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
|
|
|
|
{ wxCMD_LINE_NONE }
|
|
};
|
|
|
|
wxLog::DisableTimestamp();
|
|
|
|
wxCmdLineParser parser(cmdLineDesc, argc, argv);
|
|
switch ( parser.Parse() )
|
|
{
|
|
case -1:
|
|
// help was shown
|
|
break;
|
|
|
|
case 0:
|
|
{
|
|
// check arguments
|
|
wxVector<wxFileName> programs;
|
|
for (unsigned int i=0; i<parser.GetParamCount(); i++)
|
|
{
|
|
wxFileName fn(parser.GetParam(i));
|
|
if (!fn.IsAbsolute())
|
|
fn.MakeAbsolute();
|
|
|
|
programs.push_back(fn);
|
|
}
|
|
|
|
long timeout;
|
|
if (!parser.Found("t", &timeout))
|
|
timeout = 3;
|
|
|
|
return TestExec(programs, timeout) ? 0 : 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// syntax error
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|