ab7f057ce removes reference counting of loaded objects.

However, DuplicateModule is used extensively in X server to create
copies of modules. Without the reference counting layer DuplicateModule
cannot call LoaderOpen since at least glibc will happily realod
(possibly different) object from disk, and DuplicateModule does not
perform version checks nor module initialization.

To make it possible to unload module safely a duplicate count should be
tracked so that duplicated modules that are possibly still in use
somewhere are not uninitialized. Calling UnloadModule on a duplicated
module has no effect but no error is returned as the loader interface
does not allow for that.

Signed-off-by: Michal Suchanek <hramr...@gmail.com>
---
 hw/xfree86/loader/loaderProcs.h |    2 ++
 hw/xfree86/loader/loadmod.c     |   30 ++++++++++++++++++------------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/hw/xfree86/loader/loaderProcs.h b/hw/xfree86/loader/loaderProcs.h
index 5028554..973428b 100644
--- a/hw/xfree86/loader/loaderProcs.h
+++ b/hw/xfree86/loader/loaderProcs.h
@@ -66,6 +66,8 @@ typedef struct module_desc {
     ModuleTearDownProc TearDownProc;
     void *TearDownData;         /* returned from SetupProc */
     const XF86ModuleVersionInfo *VersionInfo;
+    struct module_desc *original;
+    int duplicate_count;
 } ModuleDesc, *ModuleDescPtr;
 
 /* External API for the loader */
diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index 8a48adb..aee2f68 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -93,8 +93,6 @@ const ModuleVersions LoaderVersionInfo = {
     ABI_FONT_VERSION
 };
 
-static int ModuleDuplicated[] = { };
-
 static void
 FreeStringList(char **paths)
 {
@@ -803,8 +801,11 @@ NewModuleDesc(const char *name)
     return mdp;
 }
 
-/* An advisory function. When true is returned unloading the module should be
- * safe. Uload can be attempted nonetheless. */
+static ModuleDescPtr ModuleGetOriginal(ModuleDescPtr mod)
+{
+    return (mod->original ? mod->original : mod);
+}
+
 int CanUnloadModule(ModuleDescPtr mod)
 {
     if (IsBuiltinModule(mod))
@@ -829,10 +830,11 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
         return NULL;
 
     ret->handle = mod->handle;
-
+    /* some code may check the procs are the same */
     ret->SetupProc = mod->SetupProc;
     ret->TearDownProc = mod->TearDownProc;
-    ret->TearDownData = ModuleDuplicated;
+    ret->original = ModuleGetOriginal(mod);
+    ret->original->duplicate_count++;
     ret->child = DuplicateModule(mod->child, ret);
     ret->sib = DuplicateModule(mod->sib, parent);
     ret->parent = parent;
@@ -1106,24 +1108,26 @@ Bool IsBuiltinModule(ModuleDescPtr mod)
 /* Is given module duplicate of another? */
 Bool IsDuplicateModule(ModuleDescPtr mod)
 {
-    return (mod->TearDownData == ModuleDuplicated);
+    return (mod->original != NULL);
 }
 
 /* Do duplicates of given module exist? */
 Bool IsDuplicated(ModuleDescPtr mod)
 {
-    /* cannot tell until reference counting is added */
-    return TRUE;
+    return (mod->duplicate_count > 0);
 }
 
 static void
 UnloadModuleOrDriver(ModuleDescPtr mod)
 {
-    if (IsBuiltinModule(mod))
+    if (mod == NULL || mod->name == NULL)
         return;
 
-    if (mod == NULL || mod->name == NULL)
+    if (!CanUnloadModule(mod)) {
+        if (IsDuplicated(mod))
+            xf86MsgVerb(X_WARNING, 3, "Cannot unload duplicated module: 
\"%s\"\n", mod->name);
         return;
+    }
 
     if (mod->parent)
         LogMessageVerbSigSafe(X_INFO, 3, "UnloadSubModule: \"%s\"\n",
@@ -1132,7 +1136,9 @@ UnloadModuleOrDriver(ModuleDescPtr mod)
         LogMessageVerbSigSafe(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
 
     RemoveChild(mod);
-    if (!IsDuplicateModule(mod)) {
+    if (IsDuplicateModule(mod)) {
+            ModuleGetOriginal(mod)->duplicate_count--;
+    } else {
         if ((mod->TearDownProc) && (mod->TearDownData))
             mod->TearDownProc(mod->TearDownData);
         LoaderUnload(mod->name, mod->handle);
-- 
1.7.10.4

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to