irssi-import / bugs.irssi.org

bugs.irssi.org archive
https://github.com/irssi/irssi/issues
0 stars 0 forks source link

module function namespace collisions #895

Open irssibot opened 10 years ago

irssibot commented 10 years ago

This is a problem that occurs due to the way modules are loaded. A function with the same name in two modules will always call the function in the first module, even if you call this function from the second module.

Background: I created two modules, and I was running into a situation where functionality in the second one was not working when the first was loaded. I ended up tracking this down to that functions from modules are loaded into a global namespace.

So if you define a function my_function() in module1.c, and load module1, and define a function with the same name, my_function(), in module2.c, and load module2, then calls to my_function() from module2 will actually call module1's my_function().

This is a bit confusing as there are no errors reported or anything about this collision.

I was able to confirm that this happened for functions both called in the module_init() function, and functions called from other places, such as in signal callbacks.

The reason this seems to occur is how the modules are loaded: in core/modules-load.c module_open() we call:

    module = g_module_open(path, (GModuleFlags) 0);

If we look at the available flags for this function:

https://developer.gnome.org/glib/2.37/glib-Dynamic-Loading-of-Modules.html#GModuleFlags

it appears that the default is to have the functions all put into a global namespace. If we change the g_module_open() calls to pass the flag G_MODULE_BIND_LOCAL, the problem goes away.

However, whether this is a true bug or whether it was designed this way for some reason I am not sure. I found it fairly confusing but I suppose it could be something that was intended and I just did not find documentation to that effect.

It can be worked around by trying to keep function names unique in your module against all other modules, though if someone were to have many modules I suppose that could get error prone.

To reproduce this, one can create two bare modules and have a function with the same name in both, and call the function with the same name from the _init() function - for example to print out the name of the module. I can provide such example modules if necessary.

I have a patch for this which I will attach.

irssibot commented 10 years ago

local_module.patch

--- src/core/modules-load.c (revision 5224)
+++ src/core/modules-load.c (working copy)
@@ -109,6 +109,7 @@
    struct stat statbuf;
    GModule *module;
    char *path, *str;
+   GModuleFlags module_flags = G_MODULE_BIND_LOCAL;

    if (g_path_is_absolute(name) || *name == '~' ||
        (*name == '.' && name[1] == G_DIR_SEPARATOR))
@@ -120,7 +121,7 @@
        g_free(str);

        if (stat(path, &statbuf) == 0) {
-           module = g_module_open(path, (GModuleFlags) 0);
+           module = g_module_open(path, module_flags);
            g_free(path);
            *found = TRUE;
            return module;
@@ -132,7 +133,7 @@
    }

    *found = stat(path, &statbuf) == 0;
-   module = g_module_open(path, (GModuleFlags) 0);
+   module = g_module_open(path, module_flags);
    g_free(path);
    return module;
 }