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