Track library handles in modules so we can dlclose what we dlopen

This commit is contained in:
K. Lange 2021-04-02 13:30:34 +09:00
parent 06bb0fdefb
commit a90ca22f4c
4 changed files with 44 additions and 19 deletions

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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));