1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: A simple execution monitor to test if wx samples crash at startup or not
4 // Author: Francesco Montorsi
8 // Copyright: (c) 2009 Francesco Montorsi
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/cmdline.h"
31 #include "wx/vector.h"
32 #include "wx/process.h"
33 #include "wx/sstream.h"
35 #include "wx/filename.h"
37 // ============================================================================
39 // ============================================================================
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 class MonitoredProcess
: public wxProcess
49 { Redirect(); m_crashed
=false; m_exitCode
=0; }
51 void OnTerminate(int WXUNUSED(pid
), int status
)
53 wxStringOutputStream stdout
, stderr
;
54 if (GetInputStream()) stdout
.Write(*GetInputStream());
55 if (GetErrorStream()) stderr
.Write(*GetErrorStream());
57 //wxPrintf("%s\n", stdout.GetString());
58 //wxPrintf("%s\n", stderr.GetString());
60 // when wx programs assert on wxGTK/wxMac, they put on stderr a message like:
61 // [Debug] date somefilename.pp(nnnn): assert "xxxxx" failed in yyyy
62 // but then the assert dialog pop-ups and thus the app doesn't exit
63 // FIXME: make assertion detection work also under other platforms
64 // see http://trac.wxwidgets.org/ticket/10697
65 m_crashed
= stdout
.GetString().Contains("assert") ||
66 stderr
.GetString().Contains("assert");
72 wxProcess::Kill(GetPid());
74 // wxProcess::Kill doesn't trigger a call to OnTerminate() normally...
75 // but we still need to call it!
82 int GetExitCode() const
83 { return m_exitCode
; }
93 MonitorData(const wxString
& cmd
) : program(cmd
) {}
96 MonitoredProcess process
;
99 // ----------------------------------------------------------------------------
101 // ----------------------------------------------------------------------------
103 bool TestExec(const wxVector
<wxFileName
>& programs
, long timeout
)
105 wxVector
<MonitorData
*> data
;
107 // run all programs specified as command line parameters
109 for (size_t i
=0; i
<programs
.size(); i
++)
111 MonitorData
*dt
= new MonitorData(programs
[i
].GetFullPath());
113 long pid
= wxExecute(programs
[i
].GetFullPath(), wxEXEC_ASYNC
, &dt
->process
);
115 wxLogError("could not run the program '%s'", programs
[i
].GetFullPath());
118 wxLogMessage("started program '%s' (pid %d)...",
119 programs
[i
].GetFullPath(), pid
);
120 wxASSERT(dt
->process
.GetPid() == pid
);
126 // sleep some moments
129 // check if all processes are still running
131 for (size_t i
=0; i
<data
.size(); i
++)
133 MonitoredProcess
& proc
= data
[i
]->process
;
134 const wxString
& prog
= data
[i
]->program
;
136 if (wxProcess::Exists(proc
.GetPid()))
140 // this typically never happens, at least when running wx-programs
141 // built with debug builds of wx (see MonitoredProcess::OnTerminate;
142 // even if an asserts fail the app doesn't automatically close!):
144 wxLogMessage("program '%s' (pid %d) is NOT running anymore...",
145 prog
, proc
.GetPid());
149 if (data
[i
]->process
.Crashed())
152 wxLogMessage("program '%s' (pid %d) crashed...",
153 prog
, proc
.GetPid());
156 wxLogMessage("program '%s' (pid %d) ended with exit code %d...",
157 prog
, proc
.GetPid(), proc
.GetExitCode());
163 // ----------------------------------------------------------------------------
165 // ----------------------------------------------------------------------------
167 int main(int argc
, char **argv
)
169 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE
, "execmon");
171 wxInitializer initializer
;
174 fprintf(stderr
, "Failed to initialize the wxWidgets library, aborting.");
178 static const wxCmdLineEntryDesc cmdLineDesc
[] =
180 { wxCMD_LINE_SWITCH
, "h", "help",
181 "show this help message",
182 wxCMD_LINE_VAL_NONE
, wxCMD_LINE_OPTION_HELP
},
183 { wxCMD_LINE_OPTION
, "t", "timeout",
184 "kills all processes still alive after 'num' seconds",
185 wxCMD_LINE_VAL_NUMBER
, 0 },
186 { wxCMD_LINE_PARAM
, "", "",
188 wxCMD_LINE_VAL_STRING
, wxCMD_LINE_PARAM_MULTIPLE
},
193 wxLog::DisableTimestamp();
195 wxCmdLineParser
parser(cmdLineDesc
, argc
, argv
);
196 switch ( parser
.Parse() )
205 wxVector
<wxFileName
> programs
;
206 for (unsigned int i
=0; i
<parser
.GetParamCount(); i
++)
208 wxFileName
fn(parser
.GetParam(i
));
209 if (!fn
.IsAbsolute())
212 programs
.push_back(fn
);
216 if (!parser
.Found("t", &timeout
))
219 return TestExec(programs
, timeout
) ? 0 : 1;