Only have one GUI plugin's shared library loaded at a time.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 03 Nov 2018 08:18:02 -0700
changeset 890 c5a3ef536a6e
parent 889 4ac9c8ff8605
child 891 f56d571bf521
Only have one GUI plugin's shared library loaded at a time.

Otherwise, GTK+3 will abort, because it checks for GTK+2 and panics if both
are loaded into a process at the same time.
gui.c
--- a/gui.c	Sat Nov 03 08:20:13 2018 -0700
+++ b/gui.c	Sat Nov 03 08:18:02 2018 -0700
@@ -15,6 +15,8 @@
     void *lib;
     const MojoGui *gui;
     MojoGuiPluginPriority priority;
+    uint32 imglen;
+    uint8 *img;
     struct S_PLUGINLIST *next;
 } PluginList;
 
@@ -71,11 +73,32 @@
         PluginList *i;
         for (i = plugins->next; i != NULL; i = i->next)
         {
-            if ( (i->priority == p) && (i->gui->init()) )
+            if (i->priority != p)
+                continue;
+
+            if (i->img != NULL)
+            {
+                i->lib = MojoPlatform_dlopen(i->img, i->imglen);
+                if (i->lib != NULL)
+                {
+                    void *addr = MojoPlatform_dlsym(i->lib, MOJOGUI_ENTRY_POINT_STR);
+                    MojoGuiEntryPoint entry = (MojoGuiEntryPoint) addr;
+                    if (entry != NULL)
+                        i->gui = entry(MOJOGUI_INTERFACE_REVISION, &GEntryPoints);
+                } // if
+            } // if
+
+            if (i->gui && i->gui->init())
             {
                 logInfo("Selected '%0' UI.", i->gui->name());
                 return i;
             } // if
+
+            if (i->lib)
+            {
+                MojoPlatform_dlclose(i->lib);
+                i->lib = NULL;
+            } // if
         } // for
     } // for
 
@@ -91,27 +114,27 @@
             plugin->gui->deinit();
         if (plugin->lib)
             MojoPlatform_dlclose(plugin->lib);
+        free(plugin->img);
         free(plugin);
     } // if
 } // deleteGuiPlugin
 
 
-static boolean tryGuiPlugin(PluginList *plugins, MojoGuiEntryPoint entry)
+static PluginList *tryGuiPlugin(PluginList *plugins, MojoGuiEntryPoint entry)
 {
-    boolean retval = false;
+    PluginList *plug = NULL;
     const MojoGui *gui = entry(MOJOGUI_INTERFACE_REVISION, &GEntryPoints);
     if (gui != NULL)
     {
-        PluginList *plug = xmalloc(sizeof (PluginList));
+        plug = xmalloc(sizeof (PluginList));
         plug->lib = NULL;
         plug->gui = gui;
         plug->priority = calcGuiPriority(gui);
         plug->next = plugins->next;
         plugins->next = plug;
-        retval = true;
     } // if
 
-    return retval;
+    return plug;
 } // tryGuiPlugin
 
 
@@ -125,32 +148,43 @@
 
 static boolean loadDynamicGuiPlugin(PluginList *plugins, MojoArchive *ar)
 {
-    boolean rc = false;
-    void *lib = NULL;
+    PluginList *plug = NULL;
     MojoInput *io = ar->openCurrentEntry(ar);
     if (io != NULL)
     {
+        void *lib = NULL;
         const uint32 imglen = (uint32) io->length(io);
         uint8 *img = (uint8 *) xmalloc(imglen);
         const uint32 br = (uint32) io->read(io, img, imglen);
         io->close(io);
         if (br == imglen)
+        {
             lib = MojoPlatform_dlopen(img, imglen);
-        free(img);
+            if (lib != NULL)
+            {
+                void *addr = MojoPlatform_dlsym(lib, MOJOGUI_ENTRY_POINT_STR);
+                MojoGuiEntryPoint entry = (MojoGuiEntryPoint) addr;
+                if (entry != NULL)
+                {
+                    plug = tryGuiPlugin(plugins, entry);
+                    if (plug)
+                    {
+                        plug->img = img;
+                        plug->imglen = imglen;
+                    } // if
+                } // if
+
+                // always close, because GTK+2 and GTK+3 can't coexist.
+                //  we'll reload them when trying them!
+                MojoPlatform_dlclose(lib);
+            } // if
+        } // if
+
+        if (!plug)
+            free(img);
     } // if
 
-    if (lib != NULL)
-    {
-        void *addr = MojoPlatform_dlsym(lib, MOJOGUI_ENTRY_POINT_STR);
-        MojoGuiEntryPoint entry = (MojoGuiEntryPoint) addr;
-        if (entry != NULL)
-        {
-            if ((rc = tryGuiPlugin(plugins, entry)) == false)
-                MojoPlatform_dlclose(lib);
-        } // if
-    } // if
-
-    return rc;
+    return plug != NULL;
 } // loadDynamicGuiPlugin
 
 
@@ -163,8 +197,7 @@
         {
             if (entinfo->type != MOJOARCHIVE_ENTRY_FILE)
                 continue;
-
-            if (strncmp(entinfo->filename, "guis/", 5) != 0)
+            else if (strncmp(entinfo->filename, "guis/", 5) != 0)
                 continue;
 
             loadDynamicGuiPlugin(plugins, GBaseArchive);