comparison src/plugincandidates.cpp @ 45:ad02dff8ebfb

Merge from branch errorcode
author Chris Cannam
date Fri, 31 Aug 2018 15:14:57 +0100
parents 0f7df035192d
children 0d2d3c89fdf6
comparison
equal deleted inserted replaced
39:a28b19b136e8 45:ad02dff8ebfb
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 /* 2 /*
3 Copyright (c) 2016 Queen Mary, University of London 3 Copyright (c) 2016-2018 Queen Mary, University of London
4 4
5 Permission is hereby granted, free of charge, to any person 5 Permission is hereby granted, free of charge, to any person
6 obtaining a copy of this software and associated documentation 6 obtaining a copy of this software and associated documentation
7 files (the "Software"), to deal in the Software without 7 files (the "Software"), to deal in the Software without
8 restriction, including without limitation the rights to use, copy, 8 restriction, including without limitation the rights to use, copy,
27 dealings in this Software without prior written authorization. 27 dealings in this Software without prior written authorization.
28 */ 28 */
29 29
30 #include "plugincandidates.h" 30 #include "plugincandidates.h"
31 31
32 #include "../version.h"
33
32 #include <set> 34 #include <set>
33 #include <stdexcept> 35 #include <stdexcept>
34 #include <iostream> 36 #include <iostream>
35 37
36 #include <QProcess> 38 #include <QProcess>
110 void 112 void
111 PluginCandidates::scan(string tag, 113 PluginCandidates::scan(string tag,
112 vector<string> pluginPath, 114 vector<string> pluginPath,
113 string descriptorSymbolName) 115 string descriptorSymbolName)
114 { 116 {
117 string helperVersion = getHelperCompatibilityVersion();
118 if (helperVersion != CHECKER_COMPATIBILITY_VERSION) {
119 log("wrong plugin checker helper version found: expected v" +
120 string(CHECKER_COMPATIBILITY_VERSION) + ", found v" +
121 helperVersion);
122 throw runtime_error("wrong version of plugin load helper found");
123 }
124
115 vector<string> libraries = getLibrariesInPath(pluginPath); 125 vector<string> libraries = getLibrariesInPath(pluginPath);
116 vector<string> remaining = libraries; 126 vector<string> remaining = libraries;
117 127
118 int runlimit = 20; 128 int runlimit = 20;
119 int runcount = 0; 129 int runcount = 0;
139 } 149 }
140 150
141 recordResult(tag, result); 151 recordResult(tag, result);
142 } 152 }
143 153
144 vector<string> 154 string
145 PluginCandidates::runHelper(vector<string> libraries, string descriptor) 155 PluginCandidates::getHelperCompatibilityVersion()
146 { 156 {
147 vector<string> output;
148
149 log("running helper " + m_helper + " with following library list:");
150 for (auto &lib: libraries) log(lib);
151
152 QProcess process; 157 QProcess process;
153 process.setReadChannel(QProcess::StandardOutput); 158 process.setReadChannel(QProcess::StandardOutput);
154 process.setProcessChannelMode(QProcess::ForwardedErrorChannel); 159 process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
155 process.start(m_helper.c_str(), { descriptor.c_str() }); 160 process.start(m_helper.c_str(), { "--version" });
161
156 if (!process.waitForStarted()) { 162 if (!process.waitForStarted()) {
157 QProcess::ProcessError err = process.error(); 163 QProcess::ProcessError err = process.error();
158 if (err == QProcess::FailedToStart) { 164 if (err == QProcess::FailedToStart) {
159 std::cerr << "Unable to start helper process " << m_helper 165 std::cerr << "Unable to start helper process " << m_helper
160 << std::endl; 166 << std::endl;
166 << " failed on startup with error code " 172 << " failed on startup with error code "
167 << err << std::endl; 173 << err << std::endl;
168 } 174 }
169 throw runtime_error("plugin load helper failed to start"); 175 throw runtime_error("plugin load helper failed to start");
170 } 176 }
177 process.waitForFinished();
178
179 QByteArray output = process.readAllStandardOutput();
180 while (output.endsWith('\n') || output.endsWith('\r')) {
181 output.chop(1);
182 }
183
184 string versionString = QString(output).toStdString();
185 log("read version string from helper: " + versionString);
186 return versionString;
187 }
188
189 vector<string>
190 PluginCandidates::runHelper(vector<string> libraries, string descriptor)
191 {
192 vector<string> output;
193
194 log("running helper " + m_helper + " with following library list:");
195 for (auto &lib: libraries) log(lib);
196
197 QProcess process;
198 process.setReadChannel(QProcess::StandardOutput);
199 process.setProcessChannelMode(QProcess::ForwardedErrorChannel);
200 process.start(m_helper.c_str(), { descriptor.c_str() });
201
202 if (!process.waitForStarted()) {
203 QProcess::ProcessError err = process.error();
204 if (err == QProcess::FailedToStart) {
205 std::cerr << "Unable to start helper process " << m_helper
206 << std::endl;
207 } else if (err == QProcess::Crashed) {
208 std::cerr << "Helper process " << m_helper
209 << " crashed on startup" << std::endl;
210 } else {
211 std::cerr << "Helper process " << m_helper
212 << " failed on startup with error code "
213 << err << std::endl;
214 }
215 throw runtime_error("plugin load helper failed to start");
216 }
217
171 for (auto &lib: libraries) { 218 for (auto &lib: libraries) {
172 process.write(lib.c_str(), lib.size()); 219 process.write(lib.c_str(), lib.size());
173 process.write("\n", 1); 220 process.write("\n", 1);
174 } 221 }
175 222
233 } 280 }
234 281
235 string status = bits[0].toStdString(); 282 string status = bits[0].toStdString();
236 283
237 string library = bits[1].toStdString(); 284 string library = bits[1].toStdString();
238 if (bits.size() == 2) library = bits[1].trimmed().toStdString(); 285 if (bits.size() == 2) {
239 286 library = bits[1].trimmed().toStdString();
240 string message = ""; 287 }
241 if (bits.size() > 2) message = bits[2].trimmed().toStdString(); 288
242
243 if (status == "SUCCESS") { 289 if (status == "SUCCESS") {
244 m_candidates[tag].push_back(library); 290 m_candidates[tag].push_back(library);
245 291
246 } else if (status == "FAILURE") { 292 } else if (status == "FAILURE") {
247 m_failures[tag].push_back({ library, message }); 293
294 QString messageAndCode = "";
295 if (bits.size() > 2) {
296 messageAndCode = bits[2].trimmed();
297 }
298
299 PluginCheckCode code = PluginCheckCode::FAIL_OTHER;
300 string message = "";
301
302 QRegExp codeRE("^(.*) *\\[([0-9]+)\\]$");
303 if (codeRE.exactMatch(messageAndCode)) {
304 QStringList caps(codeRE.capturedTexts());
305 if (caps.length() == 3) {
306 message = caps[1].toStdString();
307 code = PluginCheckCode(caps[2].toInt());
308 log("split failure report into message and failure code "
309 + caps[2].toStdString());
310 } else {
311 log("unable to split out failure code from report");
312 }
313 } else {
314 log("failure message does not give a failure code");
315 }
316
317 if (message == "") {
318 message = messageAndCode.toStdString();
319 }
320
321 m_failures[tag].push_back({ library, code, message });
248 322
249 } else { 323 } else {
250 log("unexpected status \"" + status + "\" in output line"); 324 log("unexpected status \"" + status + "\" in output line");
251 } 325 }
252 } 326 }