diff system/System.cpp @ 1165:d57f9344db19

Check for plugin loadability before trying to load in the main process (POSIX only so far)
author Chris Cannam
date Mon, 11 Jan 2016 14:18:56 +0000
parents b14064bd1f97
children afed8be79032
line wrap: on
line diff
--- a/system/System.cpp	Fri Jan 08 15:39:12 2016 +0000
+++ b/system/System.cpp	Mon Jan 11 14:18:56 2016 +0000
@@ -325,3 +325,64 @@
 double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
 float princargf(float a) { return float(princarg(a)); }
 
+#ifndef _WIN32
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+PluginLoadStatus
+TestPluginLoadability(QString soname, QString descriptorFn)
+{
+    //!!! This is POSIX only, no equivalent on Windows, where we'll
+    //!!! have to do something completely different
+    
+    pid_t pid = fork();
+
+    if (pid < 0) {
+        return UnknownPluginLoadStatus; // fork failed
+    }
+
+    if (pid == 0) { // the child process
+
+        void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL);
+        if (!handle) {
+            cerr << "isPluginLibraryLoadable: Failed to open plugin library \""
+                 << soname << "\": " << dlerror() << "\n";
+            cerr << "exiting with status 1" << endl;
+            exit(1);
+        }
+
+        void *fn = DLSYM(handle, descriptorFn.toLocal8Bit().data());
+        if (!fn) {
+            cerr << "isPluginLibraryLoadable: Failed to find plugin descriptor function \"" << descriptorFn << "\" in library \"" << soname << "\": " << dlerror() << "\n";
+            exit(2);
+        }
+
+        exit(0);
+
+    } else { // the parent process
+
+        int status = 0;
+
+        do {
+            waitpid(pid, &status, 0);
+        } while (WIFSTOPPED(status));
+
+        if (WIFEXITED(status)) {
+            switch (WEXITSTATUS(status)) {
+            case 0: return PluginLoadOK; // success
+            case 1: return PluginLoadFailedToLoadLibrary;
+            case 2: return PluginLoadFailedToFindDescriptor;
+            default: return PluginLoadFailedElsewhere;
+            }
+        }
+
+        if (WIFSIGNALED(status)) { 
+            return PluginLoadFailedElsewhere;
+        }
+
+        return UnknownPluginLoadStatus;
+    }
+}
+
+#endif