Mercurial > hg > vamp-plugin-load-checker
changeset 6:61dbb18f2369
Logging, timeouts
author | Chris Cannam |
---|---|
date | Wed, 13 Apr 2016 18:41:49 +0100 |
parents | 74064d6f5e07 |
children | 846464771d06 |
files | checker.cpp helper.cpp knownplugins.cpp knownplugins.h plugincandidates.cpp plugincandidates.h |
diffstat | 6 files changed, 71 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/checker.cpp Wed Apr 13 12:06:26 2016 +0100 +++ b/checker.cpp Wed Apr 13 18:41:49 2016 +0100 @@ -33,10 +33,17 @@ using namespace std; +struct LogCallback : PluginCandidates::LogCallback { + virtual void log(string message) { + cerr << "checker: log: " << message; + } +}; + int main(int, char **) { - KnownPlugins kp; - + LogCallback cb; + KnownPlugins kp("./helper", &cb); //!!! + for (auto t: kp.getKnownPluginTypes()) { cout << "successful libraries for plugin type \"" << kp.getTagFor(t) << "\":" << endl;
--- a/helper.cpp Wed Apr 13 12:06:26 2016 +0100 +++ b/helper.cpp Wed Apr 13 18:41:49 2016 +0100 @@ -74,6 +74,8 @@ #include <string> #include <iostream> +#include <unistd.h> + using namespace std; string error() @@ -85,23 +87,17 @@ string check(string soname, string descriptor) { -// cerr << "helper: trying: " << soname << endl; - void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL); if (!handle) { -// cerr << "helper: failed to open" << endl; return "Unable to open plugin library: " + error(); } void *fn = DLSYM(handle, descriptor); if (!fn) { -// cerr << "helper: failed to find descriptor" << endl; return "Failed to find plugin descriptor " + descriptor + " in library: " + error(); } -// cerr << "helper: succeeded" << endl; - return ""; }
--- a/knownplugins.cpp Wed Apr 13 12:06:26 2016 +0100 +++ b/knownplugins.cpp Wed Apr 13 18:41:49 2016 +0100 @@ -39,9 +39,12 @@ #define PATH_SEPARATOR ':' #endif -KnownPlugins::KnownPlugins() : - m_candidates("./helper") //!!!??? wot to do +KnownPlugins::KnownPlugins(string helperExecutableName, + PluginCandidates::LogCallback *cb) : + m_candidates(helperExecutableName) { + m_candidates.setLogCallback(cb); + m_known = { { VampPlugin,
--- a/knownplugins.h Wed Apr 13 12:06:26 2016 +0100 +++ b/knownplugins.h Wed Apr 13 18:41:49 2016 +0100 @@ -47,7 +47,8 @@ DSSIPlugin }; - KnownPlugins(); + KnownPlugins(std::string helperExecutableName, + PluginCandidates::LogCallback *cb = 0); std::vector<PluginType> getKnownPluginTypes() const { return { VampPlugin, LADSPAPlugin, DSSIPlugin };
--- a/plugincandidates.cpp Wed Apr 13 12:06:26 2016 +0100 +++ b/plugincandidates.cpp Wed Apr 13 18:41:49 2016 +0100 @@ -35,6 +35,7 @@ #include <QProcess> #include <QDir> +#include <QTime> #if defined(_WIN32) #define PLUGIN_GLOB "*.dll" @@ -47,10 +48,17 @@ using namespace std; PluginCandidates::PluginCandidates(string helperExecutableName) : - m_helper(helperExecutableName) + m_helper(helperExecutableName), + m_logCallback(0) { } +void +PluginCandidates::setLogCallback(LogCallback *cb) +{ + m_logCallback = cb; +} + vector<string> PluginCandidates::getCandidateLibrariesFor(string tag) const { @@ -65,6 +73,12 @@ else return m_failures.at(tag); } +void +PluginCandidates::log(string message) +{ + if (m_logCallback) m_logCallback->log("PluginCandidates: " + message); +} + vector<string> PluginCandidates::getLibrariesInPath(vector<string> path) { @@ -72,9 +86,7 @@ for (string dirname: path) { -//#ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE - cerr << "getLibrariesInPath: scanning directory " << dirname << endl; -//#endif + log("scanning directory " + dirname + "\n"); QDir dir(dirname.c_str(), PLUGIN_GLOB, QDir::Name | QDir::IgnoreCase, @@ -111,10 +123,9 @@ // with the plugin following the last one it reported // on. Add a failure entry for that one and continue with // the following ones. - cerr << "shortfall = " << shortfall << " (of " << remaining.size() << ")" << endl; - result.push_back("FAILURE|" + - *(remaining.rbegin() + shortfall - 1) + - "|Plugin load check failed"); + string failed = *(remaining.rbegin() + shortfall - 1); + log("helper output ended before result for plugin " + failed + "\n"); + result.push_back("FAILURE|" + failed + "|Plugin load check failed or timed out"); remaining = vector<string> (remaining.rbegin(), remaining.rbegin() + shortfall - 1); } @@ -128,8 +139,9 @@ PluginCandidates::runHelper(vector<string> libraries, string descriptor) { vector<string> output; -// cerr << "running helper with following library list:" << endl; -// for (auto &lib: libraries) cerr << lib << endl; + + log("running helper with following library list:\n"); + for (auto &lib: libraries) log(lib + "\n"); QProcess process; process.setReadChannel(QProcess::StandardOutput); @@ -144,6 +156,10 @@ process.write("\n", 1); } + QTime t; + t.start(); + int timeout = 3000; // ms + int buflen = 4096; bool done = false; @@ -155,12 +171,22 @@ done = (output.size() == libraries.size()); } else if (linelen < 0) { // error case + log("received error code while reading from helper\n"); done = true; } else { // no error, but no line read (could just be between // lines, or could be eof) done = (process.state() == QProcess::NotRunning); - if (!done) process.waitForReadyRead(100); + if (!done) { + if (t.elapsed() > timeout) { + // this is purely an emergency measure + log("timeout: helper took too long, killing it\n"); + process.kill(); + done = true; + } else { + process.waitForReadyRead(200); + } + } } } @@ -179,8 +205,11 @@ QString s(r.c_str()); QStringList bits = s.split("|"); + + log("read output line from helper: " + r); + if (bits.size() < 2 || bits.size() > 3) { - cerr << "Invalid helper output line: \"" << r << "\"" << endl; + log("invalid output line (wrong number of |-separated fields)\n"); continue; } @@ -199,8 +228,7 @@ m_failures[tag].push_back({ library, message }); } else { - cerr << "Unexpected status " << status - << " in helper output line: \"" << r << "\"" << endl; + log("unexpected status \"" + status + "\" in output line\n"); } } }
--- a/plugincandidates.h Wed Apr 13 12:06:26 2016 +0100 +++ b/plugincandidates.h Wed Apr 13 18:41:49 2016 +0100 @@ -46,13 +46,21 @@ class PluginCandidates { typedef std::vector<std::string> stringlist; - + public: /** Construct a PluginCandidates scanner that uses the given * executable as its load check helper. */ PluginCandidates(std::string helperExecutableName); + struct LogCallback { + virtual void log(std::string) = 0; + }; + + /** Set a callback to be called for log output. + */ + void setLogCallback(LogCallback *cb); + /** Scan the libraries found in the given plugin path (i.e. list * of plugin directories), checking that the given descriptor * symbol can be looked up in each. Store the results @@ -85,10 +93,12 @@ std::string m_helper; std::map<std::string, stringlist> m_candidates; std::map<std::string, std::vector<FailureRec> > m_failures; + LogCallback *m_logCallback; stringlist getLibrariesInPath(stringlist path); stringlist runHelper(stringlist libraries, std::string descriptor); void recordResult(std::string tag, stringlist results); + void log(std::string); }; #endif