Track library handles in modules so we can dlclose what we dlopen
This commit is contained in:
parent
06bb0fdefb
commit
a90ca22f4c
@ -897,6 +897,13 @@ KRK_FUNC(next,{
|
||||
return krk_pop();
|
||||
})
|
||||
|
||||
static void module_sweep(KrkInstance * inst) {
|
||||
struct KrkModule * module = (struct KrkModule*)inst;
|
||||
if (module->libHandle) {
|
||||
dlClose(module->libHandle);
|
||||
}
|
||||
}
|
||||
|
||||
_noexport
|
||||
void _createAndBind_builtins(void) {
|
||||
vm.baseClasses->objectClass = krk_newClass(S("object"), NULL);
|
||||
@ -916,6 +923,8 @@ void _createAndBind_builtins(void) {
|
||||
);
|
||||
|
||||
vm.baseClasses->moduleClass = krk_newClass(S("module"), vm.baseClasses->objectClass);
|
||||
vm.baseClasses->moduleClass->allocSize = sizeof(struct KrkModule);
|
||||
vm.baseClasses->moduleClass->_ongcsweep = module_sweep;
|
||||
krk_push(OBJECT_VAL(vm.baseClasses->moduleClass));
|
||||
krk_defineNative(&vm.baseClasses->moduleClass->methods, "__repr__", _module_repr);
|
||||
krk_defineNative(&vm.baseClasses->moduleClass->methods, "__str__", _module_repr);
|
||||
|
@ -33,3 +33,23 @@ typedef int krk_integer_type;
|
||||
#define ENABLE_STRESS_GC
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
# ifndef STATIC_ONLY
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
# define PATH_SEP "/"
|
||||
# define dlRefType void *
|
||||
# define dlSymType void *
|
||||
# define dlOpen(fileName) dlopen(fileName, RTLD_NOW)
|
||||
# define dlSym(dlRef, handlerName) dlsym(dlRef,handlerName)
|
||||
# define dlClose(dlRef) dlclose(dlRef)
|
||||
#else
|
||||
# include <windows.h>
|
||||
# define PATH_SEP "\\"
|
||||
# define dlRefType HINSTANCE
|
||||
# define dlSymType FARPROC
|
||||
# define dlOpen(fileName) LoadLibraryA(fileName)
|
||||
# define dlSym(dlRef, handlerName) GetProcAddress(dlRef, handlerName)
|
||||
# define dlClose(dlRef)
|
||||
#endif
|
||||
|
||||
|
@ -316,6 +316,15 @@ struct DictKeys {
|
||||
size_t i;
|
||||
};
|
||||
|
||||
/**
|
||||
* @extends KrkInstance
|
||||
* @brief Representation of a loaded module.
|
||||
*/
|
||||
struct KrkModule {
|
||||
KrkInstance inst;
|
||||
dlRefType libHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Yield ownership of a C string to the GC and obtain a string object.
|
||||
* @memberof KrkString
|
||||
|
25
src/vm.c
25
src/vm.c
@ -38,24 +38,6 @@
|
||||
# define KRK_BUILD_COMPILER ""
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
# ifndef STATIC_ONLY
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
# define PATH_SEP "/"
|
||||
# define dlRefType void *
|
||||
# define dlSymType void *
|
||||
# define dlOpen(fileName) dlopen(fileName, RTLD_NOW)
|
||||
# define dlSym(dlRef, handlerName) dlsym(dlRef,handlerName)
|
||||
#else
|
||||
# include <windows.h>
|
||||
# define PATH_SEP "\\"
|
||||
# define dlRefType HINSTANCE
|
||||
# define dlSymType FARPROC
|
||||
# define dlOpen(fileName) LoadLibraryA(fileName)
|
||||
# define dlSym(dlRef, handlerName) GetProcAddress(dlRef, handlerName)
|
||||
#endif
|
||||
|
||||
/* Ensure we don't have a macro for this so we can reference a local version. */
|
||||
#undef krk_currentThread
|
||||
|
||||
@ -1673,6 +1655,7 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
memcpy(&moduleOnLoad,&out,sizeof(out));
|
||||
|
||||
if (!moduleOnLoad) {
|
||||
dlClose(dlRef);
|
||||
*moduleOut = NONE_VAL();
|
||||
krk_runtimeError(vm.exceptions->importError,
|
||||
"Failed to run module initialization method '%s' from shared object '%s'",
|
||||
@ -1683,7 +1666,8 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
krk_pop(); /* onload function */
|
||||
|
||||
*moduleOut = moduleOnLoad(runAs);
|
||||
if (!IS_INSTANCE(*moduleOut)) {
|
||||
if (!krk_isInstanceOf(*moduleOut, vm.baseClasses->moduleClass)) {
|
||||
dlClose(dlRef);
|
||||
krk_runtimeError(vm.exceptions->importError,
|
||||
"Failed to load module '%s' from '%s'", runAs->chars, fileName);
|
||||
return 0;
|
||||
@ -1692,6 +1676,9 @@ int krk_loadModule(KrkString * path, KrkValue * moduleOut, KrkString * runAs) {
|
||||
krk_push(*moduleOut);
|
||||
krk_swap(1);
|
||||
|
||||
struct KrkModule * moduleAsStruct = (struct KrkModule*)AS_INSTANCE(*moduleOut);
|
||||
moduleAsStruct->libHandle = dlRef;
|
||||
|
||||
krk_attachNamedObject(&AS_INSTANCE(*moduleOut)->fields, "__name__", (KrkObj*)runAs);
|
||||
krk_attachNamedValue(&AS_INSTANCE(*moduleOut)->fields, "__file__", krk_peek(0));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user