| import core.runtime; | |
| import core.stdc.stdio; | |
| import core.stdc.string; | |
| import core.thread; | |
| import core.sys.posix.dlfcn; | |
| version (DragonFlyBSD) import core.sys.dragonflybsd.dlfcn : RTLD_NOLOAD; | |
| version (FreeBSD) import core.sys.freebsd.dlfcn : RTLD_NOLOAD; | |
| version (linux) import core.sys.linux.dlfcn : RTLD_NOLOAD; | |
| version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_NOLOAD; | |
| version (OSX) import core.sys.darwin.dlfcn : RTLD_NOLOAD; | |
| version (Solaris) import core.sys.solaris.dlfcn : RTLD_NOLOAD; | |
| static assert(__traits(compiles, RTLD_NOLOAD), "unimplemented"); | |
| void loadSym(T)(void* handle, ref T val, const char* mangle) | |
| { | |
| val = cast(T).dlsym(handle, mangle); | |
| } | |
| void* openLib(string s) | |
| { | |
| auto h = Runtime.loadLibrary(s); | |
| assert(h !is null); | |
| loadSym(h, libThrowException, "_D3lib14throwExceptionFZv"); | |
| loadSym(h, libCollectException, "_D3lib16collectExceptionFDFZvZC9Exception"); | |
| loadSym(h, libAlloc, "_D3lib5allocFZv"); | |
| loadSym(h, libTlsAlloc, "_D3lib9tls_allocFZv"); | |
| loadSym(h, libAccess, "_D3lib6accessFZv"); | |
| loadSym(h, libTlsAccess, "_D3lib10tls_accessFZv"); | |
| loadSym(h, libFree, "_D3lib4freeFZv"); | |
| loadSym(h, libTlsFree, "_D3lib8tls_freeFZv"); | |
| loadSym(h, libSharedStaticCtor, "_D3lib18shared_static_ctorOk"); | |
| loadSym(h, libSharedStaticDtor, "_D3lib18shared_static_dtorOk"); | |
| loadSym(h, libStaticCtor, "_D3lib11static_ctorOk"); | |
| loadSym(h, libStaticDtor, "_D3lib11static_dtorOk"); | |
| return h; | |
| } | |
| void closeLib(void* h) | |
| { | |
| Runtime.unloadLibrary(h); | |
| } | |
| __gshared | |
| { | |
| void function() libThrowException; | |
| Exception function(void delegate()) libCollectException; | |
| void function() libAlloc; | |
| void function() libTlsAlloc; | |
| void function() libAccess; | |
| void function() libTlsAccess; | |
| void function() libFree; | |
| void function() libTlsFree; | |
| shared uint* libSharedStaticCtor; | |
| shared uint* libSharedStaticDtor; | |
| shared uint* libStaticCtor; | |
| shared uint* libStaticDtor; | |
| } | |
| void testEH() | |
| { | |
| bool passed; | |
| try | |
| libThrowException(); | |
| catch (Exception e) | |
| passed = true; | |
| assert(passed); passed = false; | |
| assert(libCollectException({throw new Exception(null);}) !is null); | |
| assert(libCollectException({libThrowException();}) !is null); | |
| } | |
| void testGC() | |
| { | |
| import core.memory; | |
| libAlloc(); | |
| libTlsAlloc(); | |
| libAccess(); | |
| libTlsAccess(); | |
| GC.collect(); | |
| libTlsAccess(); | |
| libAccess(); | |
| libTlsFree(); | |
| libFree(); | |
| } | |
| void testInit() | |
| { | |
| assert(*libStaticCtor == 1); | |
| assert(*libStaticDtor == 0); | |
| static void run() | |
| { | |
| assert(*libSharedStaticCtor == 1); | |
| assert(*libSharedStaticDtor == 0); | |
| assert(*libStaticCtor == 2); | |
| assert(*libStaticDtor == 0); | |
| } | |
| auto thr = new Thread(&run); | |
| thr.start(); | |
| thr.join(); | |
| assert(*libSharedStaticCtor == 1); | |
| assert(*libSharedStaticDtor == 0); | |
| assert(*libStaticCtor == 2); | |
| assert(*libStaticDtor == 1); | |
| } | |
| const(ModuleInfo)* findModuleInfo(string name) | |
| { | |
| foreach (m; ModuleInfo) | |
| if (m.name == name) return m; | |
| return null; | |
| } | |
| void runTests(string libName) | |
| { | |
| assert(findModuleInfo("lib") is null); | |
| auto handle = openLib(libName); | |
| assert(findModuleInfo("lib") !is null); | |
| testEH(); | |
| testGC(); | |
| testInit(); | |
| closeLib(handle); | |
| assert(findModuleInfo("lib") is null); | |
| } | |
| void main(string[] args) | |
| { | |
| auto name = args[0] ~ '\0'; | |
| const pathlen = strrchr(name.ptr, '/') - name.ptr + 1; | |
| name = name[0 .. pathlen] ~ "lib.so"; | |
| runTests(name); | |
| // lib is no longer resident | |
| name ~= '\0'; | |
| assert(.dlopen(name.ptr, RTLD_LAZY | RTLD_NOLOAD) is null); | |
| name = name[0 .. $-1]; | |
| auto thr = new Thread({runTests(name);}); | |
| thr.start(); | |
| thr.join(); | |
| } |