]> git.saurik.com Git - wxWidgets.git/blame - utils/execmon/execmon.cpp
Change version to 3.0.0.
[wxWidgets.git] / utils / execmon / execmon.cpp
CommitLineData
aa113d87
FM
1/////////////////////////////////////////////////////////////////////////////
2// Name: execmon.cpp
3// Purpose: A simple execution monitor to test if wx samples crash at startup or not
4// Author: Francesco Montorsi
5// Modified by:
6// Created: 25/3/09
aa113d87 7// Copyright: (c) 2009 Francesco Montorsi
526954c5 8// Licence: wxWindows licence
aa113d87
FM
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
dbe31039
VZ
27 #include "wx/app.h"
28 #include "wx/log.h"
aa113d87
FM
29#endif // WX_PRECOMP
30
31#include "wx/cmdline.h"
32#include "wx/vector.h"
33#include "wx/process.h"
34#include "wx/sstream.h"
35#include "wx/utils.h"
36#include "wx/filename.h"
40531a9f
FM
37#include "wx/app.h"
38#include "wx/log.h"
aa113d87
FM
39
40// ============================================================================
41// implementation
42// ============================================================================
43
44// ----------------------------------------------------------------------------
45// utility classes
46// ----------------------------------------------------------------------------
47
48class MonitoredProcess : public wxProcess
49{
50public:
51 MonitoredProcess()
52 { Redirect(); m_crashed=false; m_exitCode=0; }
3814912f 53
aa113d87
FM
54 void OnTerminate(int WXUNUSED(pid), int status)
55 {
3814912f
VZ
56 wxStringOutputStream out, err;
57 if (GetInputStream()) out.Write(*GetInputStream());
58 if (GetErrorStream()) err.Write(*GetErrorStream());
59
aa113d87
FM
60 //wxPrintf("%s\n", stdout.GetString());
61 //wxPrintf("%s\n", stderr.GetString());
62
63 // when wx programs assert on wxGTK/wxMac, they put on stderr a message like:
64 // [Debug] date somefilename.pp(nnnn): assert "xxxxx" failed in yyyy
65 // but then the assert dialog pop-ups and thus the app doesn't exit
66 // FIXME: make assertion detection work also under other platforms
67 // see http://trac.wxwidgets.org/ticket/10697
3814912f
VZ
68 m_crashed = out.GetString().Contains("assert") ||
69 err.GetString().Contains("assert");
aa113d87
FM
70 m_exitCode = status;
71 }
3814912f 72
aa113d87
FM
73 void Kill()
74 {
75 wxProcess::Kill(GetPid());
3814912f 76
aa113d87
FM
77 // wxProcess::Kill doesn't trigger a call to OnTerminate() normally...
78 // but we still need to call it!
79 OnTerminate(0, -1);
80 }
3814912f 81
aa113d87
FM
82 bool Crashed() const
83 { return m_crashed; }
3814912f 84
aa113d87
FM
85 int GetExitCode() const
86 { return m_exitCode; }
3814912f 87
aa113d87
FM
88private:
89 bool m_crashed;
90 int m_exitCode;
91};
92
93class MonitorData
94{
95public:
96 MonitorData(const wxString& cmd) : program(cmd) {}
97
98 wxString program;
99 MonitoredProcess process;
100};
101
102// ----------------------------------------------------------------------------
103// the real main
104// ----------------------------------------------------------------------------
105
106bool TestExec(const wxVector<wxFileName>& programs, long timeout)
107{
3814912f 108 size_t i;
aa113d87 109 wxVector<MonitorData*> data;
3814912f 110
aa113d87
FM
111 // run all programs specified as command line parameters
112 wxArrayLong procID;
3814912f 113 for (i=0; i<programs.size(); i++)
aa113d87
FM
114 {
115 MonitorData *dt = new MonitorData(programs[i].GetFullPath());
3814912f 116
aa113d87
FM
117 long pid = wxExecute(programs[i].GetFullPath(), wxEXEC_ASYNC, &dt->process);
118 if (pid == 0)
43b2d5e7 119 {
aa113d87 120 wxLogError("could not run the program '%s'", programs[i].GetFullPath());
43b2d5e7 121 }
aa113d87
FM
122 else
123 {
3814912f 124 wxLogMessage("started program '%s' (pid %d)...",
aa113d87
FM
125 programs[i].GetFullPath(), pid);
126 wxASSERT(dt->process.GetPid() == pid);
127
128 data.push_back(dt);
129 }
130 }
3814912f 131
aa113d87
FM
132 // sleep some moments
133 wxSleep(timeout);
3814912f 134
aa113d87
FM
135 // check if all processes are still running
136 bool allok = true;
3814912f 137 for (i=0; i<data.size(); i++)
aa113d87
FM
138 {
139 MonitoredProcess& proc = data[i]->process;
140 const wxString& prog = data[i]->program;
3814912f 141
aa113d87
FM
142 if (wxProcess::Exists(proc.GetPid()))
143 proc.Kill();
144 else
145 {
146 // this typically never happens, at least when running wx-programs
147 // built with debug builds of wx (see MonitoredProcess::OnTerminate;
148 // even if an asserts fail the app doesn't automatically close!):
3814912f
VZ
149
150 wxLogMessage("program '%s' (pid %d) is NOT running anymore...",
aa113d87
FM
151 prog, proc.GetPid());
152 allok = false;
153 }
154
155 if (data[i]->process.Crashed())
156 {
157 allok = false;
3814912f 158 wxLogMessage("program '%s' (pid %d) crashed...",
aa113d87
FM
159 prog, proc.GetPid());
160 }
161 else
3814912f 162 wxLogMessage("program '%s' (pid %d) ended with exit code %d...",
aa113d87
FM
163 prog, proc.GetPid(), proc.GetExitCode());
164 }
3814912f 165
aa113d87
FM
166 return allok;
167}
168
169// ----------------------------------------------------------------------------
170// main
171// ----------------------------------------------------------------------------
172
173int main(int argc, char **argv)
174{
175 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "execmon");
176
177 wxInitializer initializer;
178 if ( !initializer )
179 {
180 fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
181 return -1;
182 }
183
184 static const wxCmdLineEntryDesc cmdLineDesc[] =
185 {
3814912f 186 { wxCMD_LINE_SWITCH, "h", "help",
aa113d87
FM
187 "show this help message",
188 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
3814912f 189 { wxCMD_LINE_OPTION, "t", "timeout",
aa113d87
FM
190 "kills all processes still alive after 'num' seconds",
191 wxCMD_LINE_VAL_NUMBER, 0 },
3814912f 192 { wxCMD_LINE_PARAM, "", "",
aa113d87
FM
193 "program-to-run",
194 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
195
196 { wxCMD_LINE_NONE }
197 };
3814912f 198
aa113d87
FM
199 wxLog::DisableTimestamp();
200
201 wxCmdLineParser parser(cmdLineDesc, argc, argv);
202 switch ( parser.Parse() )
203 {
204 case -1:
205 // help was shown
206 break;
207
208 case 0:
209 {
210 // check arguments
211 wxVector<wxFileName> programs;
212 for (unsigned int i=0; i<parser.GetParamCount(); i++)
213 {
214 wxFileName fn(parser.GetParam(i));
215 if (!fn.IsAbsolute())
216 fn.MakeAbsolute();
3814912f 217
aa113d87
FM
218 programs.push_back(fn);
219 }
3814912f 220
aa113d87
FM
221 long timeout;
222 if (!parser.Found("t", &timeout))
223 timeout = 3;
3814912f 224
aa113d87
FM
225 return TestExec(programs, timeout) ? 0 : 1;
226 }
227 break;
228
229 default:
230 // syntax error
231 break;
232 }
233
234 return 0;
235}
236