annotate helper.cpp @ 4:6f891a9c6434

Make checker with hard-coded knowledge about various plugin types and paths; fix some process management problems
author Chris Cannam
date Wed, 13 Apr 2016 12:00:07 +0100
parents 2288c1d05c28
children 74064d6f5e07
rev   line source
Chris@2 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /**
Chris@1 4 * Plugin Load Checker Helper
Chris@0 5 *
Chris@4 6 * This program accepts the name of a descriptor symbol as its only
Chris@1 7 * command-line argument. It then reads a list of plugin library paths
Chris@1 8 * from stdin, one per line. For each path read, it attempts to load
Chris@4 9 * that library and retrieve the named descriptor symbol, printing a
Chris@1 10 * line to stdout reporting whether this was successful or not and
Chris@1 11 * then flushing stdout. The output line format is described
Chris@1 12 * below. The program exits with code 0 if all libraries were loaded
Chris@1 13 * successfully and non-zero otherwise.
Chris@0 14 *
Chris@0 15 * Note that library paths must be ready to pass to dlopen() or
Chris@0 16 * equivalent; this usually means they should be absolute paths.
Chris@0 17 *
Chris@0 18 * Output line for successful load of library libname.so:
Chris@0 19 * SUCCESS|/path/to/libname.so|
Chris@0 20 *
Chris@0 21 * Output line for failed load of library libname.so:
Chris@0 22 * FAILURE|/path/to/libname.so|Reason for failure if available
Chris@0 23 *
Chris@2 24 * Sometimes plugins will crash completely on load, bringing down this
Chris@2 25 * program with them. If the program exits before all listed plugins
Chris@2 26 * have been checked, this means that the plugin following the last
Chris@2 27 * reported one has crashed. Typically the caller may want to run it
Chris@2 28 * again, omitting that plugin.
Chris@0 29 */
Chris@0 30
Chris@0 31 #ifdef _WIN32
Chris@0 32 #include <windows.h>
Chris@0 33 #include <process.h>
Chris@0 34 #define DLOPEN(a,b) LoadLibrary((a).toStdWString().c_str())
Chris@0 35 #define DLSYM(a,b) GetProcAddress((HINSTANCE)(a),(b))
Chris@0 36 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a)))
Chris@0 37 #define DLERROR() ""
Chris@0 38 #else
Chris@0 39 #include <dlfcn.h>
Chris@0 40 #define DLOPEN(a,b) dlopen((a).c_str(),(b))
Chris@0 41 #define DLSYM(a,b) dlsym((a),(b).c_str())
Chris@0 42 #define DLCLOSE(a) dlclose((a))
Chris@0 43 #define DLERROR() dlerror()
Chris@0 44 #endif
Chris@0 45
Chris@0 46 #include <string>
Chris@0 47 #include <iostream>
Chris@0 48
Chris@0 49 using namespace std;
Chris@0 50
Chris@0 51 string error()
Chris@0 52 {
Chris@0 53 string e = dlerror();
Chris@0 54 if (e == "") return "(unknown error)";
Chris@0 55 else return e;
Chris@0 56 }
Chris@0 57
Chris@1 58 string check(string soname, string descriptor)
Chris@0 59 {
Chris@4 60 // cerr << "helper: trying: " << soname << endl;
Chris@4 61
Chris@0 62 void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL);
Chris@0 63 if (!handle) {
Chris@4 64 // cerr << "helper: failed to open" << endl;
Chris@0 65 return "Unable to open plugin library: " + error();
Chris@0 66 }
Chris@0 67
Chris@0 68 void *fn = DLSYM(handle, descriptor);
Chris@0 69 if (!fn) {
Chris@4 70 // cerr << "helper: failed to find descriptor" << endl;
Chris@0 71 return "Failed to find plugin descriptor " + descriptor +
Chris@0 72 " in library: " + error();
Chris@0 73 }
Chris@0 74
Chris@4 75 // cerr << "helper: succeeded" << endl;
Chris@4 76
Chris@0 77 return "";
Chris@0 78 }
Chris@0 79
Chris@0 80 int main(int argc, char **argv)
Chris@0 81 {
Chris@0 82 bool allGood = true;
Chris@0 83 string soname;
Chris@0 84
Chris@1 85 if (argc != 2) {
Chris@1 86 cerr << "\nUsage:\n " << argv[0] << " descriptorname\n"
Chris@4 87 "\nwhere descriptorname is the name of a plugin descriptor symbol to be sought\n"
Chris@1 88 "in each library (e.g. vampGetPluginDescriptor for Vamp plugins). The list of\n"
Chris@1 89 "candidate plugin library filenames is read from stdin.\n" << endl;
Chris@1 90 return 2;
Chris@1 91 }
Chris@1 92
Chris@1 93 string descriptor = argv[1];
Chris@1 94
Chris@0 95 while (getline(cin, soname)) {
Chris@1 96 string report = check(soname, descriptor);
Chris@0 97 if (report != "") {
Chris@0 98 cout << "FAILURE|" << soname << "|" << report << endl;
Chris@0 99 allGood = false;
Chris@0 100 } else {
Chris@0 101 cout << "SUCCESS|" << soname << "|" << endl;
Chris@0 102 }
Chris@0 103 }
Chris@0 104
Chris@0 105 return allGood ? 0 : 1;
Chris@0 106 }