[Issue 14824] A stale function might get called when unloading shared libraries on FBSD
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Thu Sep 10 07:13:05 PDT 2015
https://issues.dlang.org/show_bug.cgi?id=14824
ponce <aliloko at gmail.com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |aliloko at gmail.com
--- Comment #1 from ponce <aliloko at gmail.com> ---
I'm hitting a very similar bug on OS X 10.10.4, let me explain.
== Setup ==
Here the host program source.
What it does is:
- for each dynlib in command line:
- load dynlibs
- call the VSTPluginMain function if it exist,
- unload it
--------------------- ldvst.cpp --------------------
#include <dlfcn.h>
#include <cstdio>
#include <cstring>
#include <vector>
typedef __cdecl void* (*VSTPluginMain_t)(void*);
int main(int argc, char**argv)
{
std::vector<char*> dllPaths;
if (argc < 2)
{
printf("usage: ldvst [-lazy] <thing.vst>\n");
return 1;
}
bool lazy = false;
for (int i = 1; i < argc; ++i)
{
char* arg = argv[i];
if (strcmp(arg, "-lazy") == 0)
lazy = true;
else if (strcmp(arg, "-now") == 0)
lazy = false;
else
dllPaths.push_back(arg);
}
for (int i = 0; i < dllPaths.size(); ++i)
{
char* dllPath = dllPaths[i];
printf("dlopen(%s)\n", dllPath);
void* handle = dlopen(dllPath, lazy ? RTLD_LAZY : RTLD_NOW);
if (handle == NULL)
{
printf("error: dlopen of %s failed\n", dllPath);
return 2;
}
VSTPluginMain_t VSTPluginMain = (VSTPluginMain_t) dlsym(handle,
"VSTPluginMain");
printf("dlsym returned %p\n", (void*)VSTPluginMain);
if (VSTPluginMain != NULL)
{
void* result = VSTPluginMain(NULL);
printf("VSTPluginMain returned %p\n", result);
}
printf("dlclose(%s)\n\n", dllPath);
dlclose(handle);
}
return 0;
}
-----------------------------------------------------
The host is compiled with:
$ clang++ ldvst.cpp -o ldvst-cpp
Here the whole dynlib source:
----------------- distort.d -------------------------
extern(C) void* VSTPluginMain(void* hostCallback)
{
import core.runtime;
Runtime.initialize();
import std.stdio;
import core.stdc.stdio;
printf("Hello !\n");
Runtime.terminate();
return null;
}
------------------------------------------------------
This dynlib can be built with ldc:
$ ldc2 -shared -oflibdistort.so -g -w -I. distort.d -relocation-model=pic
or with dmd
$ dmd -c -ofdistort.o -debug -g -w -version=Have_distort -I. distort.d -fPIC
$ dmd -oflibdistort.so distort.o -shared -g
For the purpose of demonstration you need another C dynlib, for example
/System/Library/Frameworks/Cocoa.framework/Cocoa on OS X.
Now the bug triggers when calling:
== How to reproduce ==
$ ldvst-cpp libdistort.so
=> works
$ ldvst-cpp libdistort.so libdistort.so
=> works
$ ldvst-cpp /System/Library/Frameworks/Cocoa.framework/Cocoa libdistort.so
=> works
$ ldvst-cpp libdistort.so /System/Library/Frameworks/Cocoa.framework/Cocoa
=> FAIL, and that's precisely the case that happen in production :(
$ ldvst-cpp /System/Library/Frameworks/Cocoa.framework/Cocoa libdistort.so
/System/Library/Frameworks/Cocoa.framework/Cocoa
=> works
In other words, if the host program loads a D dynlib first, then a C dynlib,
then the second dlopen fail.
This has eluded me for a complete month.
--
More information about the Digitalmars-d-bugs
mailing list