Change the way modules are destroyed;

They are now destroyed explicitly after tearing down the Lua state
instead of relying on finalizers.  It's definitely annoying to make it
coordinated in a centralized way like this instead of being distributed,
but there's not really any reliabel way to ensure that graphics objects
are destroyed before the graphics module/device is destroyed, which is a
problem.
This commit is contained in:
bjorn 2022-08-04 21:44:34 -07:00
parent aa4fce2842
commit 019814e2c1
13 changed files with 59 additions and 33 deletions

View File

@ -28,6 +28,17 @@ LOVR_EXPORT int luaopen_lovr_system(lua_State* L);
LOVR_EXPORT int luaopen_lovr_thread(lua_State* L);
LOVR_EXPORT int luaopen_lovr_timer(lua_State* L);
void lovrAudioDestroy(void);
void lovrEventDestroy(void);
void lovrFilesystemDestroy(void);
void lovrGraphicsDestroy(void);
void lovrHeadsetDestroy(void);
void lovrMathDestroy(void);
void lovrPhysicsDestroy(void);
void lovrSystemDestroy(void);
void lovrThreadModuleDestroy(void);
void lovrTimerDestroy(void);
// Object names are lightuserdata because Variants need a non-Lua string due to threads.
static int luax_meta__tostring(lua_State* L) {
lua_getfield(L, -1, "__info");
@ -116,6 +127,40 @@ void luax_preload(lua_State* L) {
lua_pop(L, 2);
}
// Destroys modules in a specific order
void luax_unload(lua_State* L) {
#ifndef LOVR_DISABLE_TIMER
lovrTimerDestroy();
#endif
#ifndef LOVR_DISABLE_MATH
lovrMathDestroy();
#endif
#ifndef LOVR_DISABLE_EVENT
lovrEventDestroy();
#endif
#ifndef LOVR_DISABLE_THREAD
lovrThreadModuleDestroy();
#endif
#ifndef LOVR_DISABLE_PHYSICS
lovrPhysicsDestroy();
#endif
#ifndef LOVR_DISABLE_AUDIO
lovrAudioDestroy();
#endif
#ifndef LOVR_DISABLE_HEADSET
lovrHeadsetDestroy();
#endif
#ifndef LOVR_DISABLE_GRAPHICS
lovrGraphicsDestroy();
#endif
#ifndef LOVR_DISABLE_SYSTEM
lovrSystemDestroy();
#endif
#ifndef LOVR_DISABLE_FILESYSTEM
lovrFilesystemDestroy();
#endif
}
void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions, destructorFn* destructor) {
// Push metatable

View File

@ -111,6 +111,7 @@ typedef struct {
#define luax_clearerror(L) lua_pushnil(L), luax_seterror(L)
void luax_preload(struct lua_State* L);
void luax_unload(struct lua_State* L);
void _luax_registertype(struct lua_State* L, const char* name, const struct luaL_Reg* functions, void (*destructor)(void*));
void* _luax_totype(struct lua_State* L, int index, uint64_t hash);
void* _luax_checktype(struct lua_State* L, int index, uint64_t hash, const char* debug);

View File

@ -331,7 +331,6 @@ int luaopen_lovr_audio(lua_State* L) {
lua_pop(L, 1);
if (lovrAudioInit(spatializer, sampleRate)) {
luax_atexit(L, lovrAudioDestroy);
if (start) {
lovrAudioSetDevice(AUDIO_PLAYBACK, NULL, 0, NULL, AUDIO_SHARED);
lovrAudioStart(AUDIO_PLAYBACK);

View File

@ -214,9 +214,6 @@ int luaopen_lovr_event(lua_State* L) {
lua_pushcfunction(L, nextEvent);
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
if (lovrEventInit()) {
luax_atexit(L, lovrEventDestroy);
}
lovrEventInit();
return 1;
}

View File

@ -516,9 +516,7 @@ int luaopen_lovr_filesystem(lua_State* L) {
}
lua_pop(L, 1);
if (lovrFilesystemInit(archive)) {
luax_atexit(L, lovrFilesystemDestroy);
}
lovrFilesystemInit(archive);
lua_newtable(L);
luax_register(L, lovrFilesystem);

View File

@ -658,17 +658,10 @@ static int l_lovrGraphicsInit(lua_State* L) {
if (shaderCache) {
config.cacheData = luax_readfile(".lovrshadercache", &config.cacheSize);
luax_atexit(L, luax_writeshadercache);
}
if (lovrGraphicsInit(&config)) {
luax_atexit(L, lovrGraphicsDestroy);
// Finalizers run in the opposite order they were added, so this has to go last
if (shaderCache) {
luax_atexit(L, luax_writeshadercache);
}
}
lovrGraphicsInit(&config);
return 0;
}

View File

@ -672,7 +672,6 @@ int luaopen_lovr_headset(lua_State* L) {
}
lua_pop(L, 1);
luax_atexit(L, lovrHeadsetDestroy);
lovrHeadsetInit(&config);
return 1;
}

View File

@ -389,9 +389,7 @@ int luaopen_lovr_math(lua_State* L) {
lua_pop(L, 1);
// Module
if (lovrMathInit()) {
luax_atexit(L, lovrMathDestroy);
}
lovrMathInit();
// Each Lua state gets its own thread-local Pool
pool = lovrPoolCreate();

View File

@ -169,8 +169,6 @@ int luaopen_lovr_physics(lua_State* L) {
luax_registertype(L, CapsuleShape);
luax_registertype(L, CylinderShape);
luax_registertype(L, MeshShape);
if (lovrPhysicsInit()) {
luax_atexit(L, lovrPhysicsDestroy);
}
lovrPhysicsInit();
return 1;
}

View File

@ -205,8 +205,6 @@ static const luaL_Reg lovrSystem[] = {
int luaopen_lovr_system(lua_State* L) {
lua_newtable(L);
luax_register(L, lovrSystem);
if (lovrSystemInit()) {
luax_atexit(L, lovrSystemDestroy);
}
lovrSystemInit();
return 1;
}

View File

@ -110,8 +110,6 @@ int luaopen_lovr_thread(lua_State* L) {
luax_register(L, lovrThreadModule);
luax_registertype(L, Thread);
luax_registertype(L, Channel);
if (lovrThreadModuleInit()) {
luax_atexit(L, lovrThreadModuleDestroy);
}
lovrThreadModuleInit();
return 1;
}

View File

@ -47,8 +47,7 @@ static const luaL_Reg lovrTimer[] = {
int luaopen_lovr_timer(lua_State* L) {
lua_newtable(L);
luax_register(L, lovrTimer);
if (lovrTimerInit()) {
luax_atexit(L, lovrTimerDestroy);
}
lovrTimerInit();
luax_atexit(L, lovrTimerDestroy);
return 1;
}

View File

@ -132,6 +132,7 @@ int main(int argc, char** argv) {
memset(&cookie.value, 0, sizeof(cookie.value));
}
lua_close(L);
luax_unload(L);
} while (restart);
os_destroy();
@ -147,6 +148,7 @@ void lovrDestroy(void* arg) {
lua_State* L = context->L;
emscripten_cancel_main_loop();
lua_close(L);
luax_unload(L);
os_destroy();
}
}
@ -165,6 +167,7 @@ static void emscriptenLoop(void* arg) {
}
lua_close(context->L);
luax_unload(L);
emscripten_cancel_main_loop();
if (restart) {