Fix module destruction;

There is a problem when a Thread stops: it destroys all of the modules
that it required.  This is because we unconditionally call luax_atexit
when modules are required, and when the thread lua_State dies it takes
all of the modules with it.  To fix this, lovr<Module>Init will return
whether or not initialization successfully happened, which provides us
with enough info to know if we should place the luax_atexit destructor
This commit is contained in:
bjorn 2018-11-19 08:08:56 -08:00 committed by Bjorn Swenson
parent 465e5c2010
commit 0e99d47394
27 changed files with 69 additions and 54 deletions

View File

@ -223,9 +223,10 @@ static const luaL_Reg lovrAudio[] = {
int luaopen_lovr_audio(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrAudio);
luax_atexit(L, lovrAudioDestroy);
luax_registertype(L, "Microphone", lovrMicrophone);
luax_registertype(L, "Source", lovrSource);
lovrAudioInit();
if (lovrAudioInit()) {
luax_atexit(L, lovrAudioDestroy);
}
return 1;
}

View File

@ -178,12 +178,14 @@ static const luaL_Reg lovrEvent[] = {
int luaopen_lovr_event(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrEvent);
luax_atexit(L, lovrEventDestroy);
// Store nextEvent in the registry to avoid creating a closure every time we poll for events.
lua_pushcfunction(L, nextEvent);
pollRef = luaL_ref(L, LUA_REGISTRYINDEX);
lovrEventInit();
if (lovrEventInit()) {
luax_atexit(L, lovrEventDestroy);
}
return 1;
}

View File

@ -360,10 +360,6 @@ static const luaL_Reg lovrFilesystem[] = {
};
int luaopen_lovr_filesystem(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrFilesystem);
luax_atexit(L, lovrFilesystemDestroy);
lua_getglobal(L, "arg");
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "exe");
@ -372,13 +368,19 @@ int luaopen_lovr_filesystem(lua_State* L) {
const char* argGame = lua_tostring(L, -1);
lua_getfield(L, -3, "root");
const char* argRoot = luaL_optstring(L, -1, NULL);
lovrFilesystemInit(argExe, argGame, argRoot);
if (lovrFilesystemInit(argExe, argGame, argRoot)) {
luax_atexit(L, lovrFilesystemDestroy);
}
lua_pop(L, 4);
} else {
lua_pop(L, 1);
lovrFilesystemInit(NULL, NULL, NULL);
if (lovrFilesystemInit(NULL, NULL, NULL)) {
luax_atexit(L, lovrFilesystemDestroy);
}
}
lua_newtable(L);
luaL_register(L, NULL, lovrFilesystem);
luax_registerloader(L, moduleLoader, 2);
luax_registerloader(L, libraryLoader, 3);
return 1;

View File

@ -299,6 +299,7 @@ static int l_lovrGraphicsSetWindow(lua_State* L) {
lua_pop(L, 1);
lovrGraphicsSetWindow(&flags);
luax_atexit(L, lovrGraphicsDestroy); // The lua_State that creates the window shall be the one to destroy it
lovrRelease(textureData);
return 0;
}
@ -1390,7 +1391,6 @@ static const luaL_Reg lovrGraphics[] = {
int luaopen_lovr_graphics(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrGraphics);
luax_atexit(L, lovrGraphicsDestroy);
luax_registertype(L, "Animator", lovrAnimator);
luax_registertype(L, "Font", lovrFont);
luax_registertype(L, "Material", lovrMaterial);

View File

@ -349,7 +349,6 @@ static const luaL_Reg lovrHeadset[] = {
int luaopen_lovr_headset(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrHeadset);
luax_atexit(L, lovrHeadsetDestroy);
luax_registertype(L, "Controller", lovrController);
luax_pushconf(L);
@ -391,7 +390,10 @@ int luaopen_lovr_headset(lua_State* L) {
lua_pop(L, 1);
}
lovrHeadsetInit(drivers.data, drivers.length, offset, msaa);
if (lovrHeadsetInit(drivers.data, drivers.length, offset, msaa)) {
luax_atexit(L, lovrHeadsetDestroy);
}
lovrHeadsetDriver->setMirrored(mirror, mirrorEye);
vec_deinit(&drivers);

View File

@ -181,10 +181,11 @@ static const luaL_Reg lovrMath[] = {
int luaopen_lovr_math(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrMath);
luax_atexit(L, lovrMathDestroy);
luax_registertype(L, "Curve", lovrCurve);
luax_registertype(L, "RandomGenerator", lovrRandomGenerator);
luax_registertype(L, "Transform", lovrTransform);
lovrMathInit();
if (lovrMathInit()) {
luax_atexit(L, lovrMathDestroy);
}
return 1;
}

View File

@ -150,7 +150,6 @@ static const luaL_Reg lovrPhysics[] = {
int luaopen_lovr_physics(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrPhysics);
luax_atexit(L, lovrPhysicsDestroy);
luax_registertype(L, "World", lovrWorld);
luax_registertype(L, "Collider", lovrCollider);
luax_extendtype(L, "Joint", "BallJoint", lovrJoint, lovrBallJoint);
@ -161,6 +160,8 @@ int luaopen_lovr_physics(lua_State* L) {
luax_extendtype(L, "Shape", "BoxShape", lovrShape, lovrBoxShape);
luax_extendtype(L, "Shape", "CapsuleShape", lovrShape, lovrCapsuleShape);
luax_extendtype(L, "Shape", "CylinderShape", lovrShape, lovrCylinderShape);
lovrPhysicsInit();
if (lovrPhysicsInit()) {
luax_atexit(L, lovrPhysicsDestroy);
}
return 1;
}

View File

@ -66,10 +66,11 @@ static const luaL_Reg lovrThreadModule[] = {
int luaopen_lovr_thread(lua_State* L) {
lua_newtable(L);
luax_atexit(L, lovrThreadDeinit);
luaL_register(L, NULL, lovrThreadModule);
luax_registertype(L, "Thread", lovrThread);
luax_registertype(L, "Channel", lovrChannel);
lovrThreadInit();
if (lovrThreadInit()) {
luax_atexit(L, lovrThreadDeinit);
}
return 1;
}

View File

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

View File

@ -19,8 +19,8 @@ ALenum lovrAudioConvertFormat(int bitDepth, int channelCount) {
return 0;
}
void lovrAudioInit() {
if (state.initialized) return;
bool lovrAudioInit() {
if (state.initialized) return false;
ALCdevice* device = alcOpenDevice(NULL);
lovrAssert(device, "Unable to open default audio device");
@ -46,7 +46,7 @@ void lovrAudioInit() {
quat_set(state.orientation, 0, 0, 0, -1);
vec3_set(state.position, 0, 0, 0);
vec3_set(state.velocity, 0, 0, 0);
state.initialized = true;
return state.initialized = true;
}
void lovrAudioDestroy() {

View File

@ -23,7 +23,7 @@ typedef struct {
ALenum lovrAudioConvertFormat(int bitDepth, int channelCount);
void lovrAudioInit();
bool lovrAudioInit();
void lovrAudioDestroy();
void lovrAudioUpdate();
void lovrAudioAdd(Source* source);

View File

@ -5,13 +5,13 @@
static EventState state;
void lovrEventInit() {
if (state.initialized) return;
bool lovrEventInit() {
if (state.initialized) return false;
vec_init(&state.pumps);
vec_init(&state.events);
lovrEventAddPump(lovrPlatformPollEvents);
atexit(lovrEventDestroy);
state.initialized = true;
return state.initialized = true;
}
void lovrEventDestroy() {

View File

@ -90,7 +90,7 @@ typedef struct {
vec_event_t events;
} EventState;
void lovrEventInit();
bool lovrEventInit();
void lovrEventDestroy();
void lovrEventAddPump(EventPump pump);
void lovrEventRemovePump(EventPump pump);

View File

@ -31,8 +31,8 @@ const char lovrDirSep = '/';
static FilesystemState state;
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot) {
if (state.initialized) return;
bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot) {
if (state.initialized) return false;
state.initialized = true;
if (!PHYSFS_init(argExe)) {
@ -55,13 +55,15 @@ void lovrFilesystemInit(const char* argExe, const char* argGame, const char* arg
if (argGame) {
strncpy(state.source, argGame, LOVR_PATH_MAX);
if (!lovrFilesystemMount(state.source, NULL, 1, argRoot)) { // Attempt to load from arg. If success, init is done
return;
return true;
}
}
free(state.source); // Couldn't load from argProject, so apparently it isn't the source
state.source = NULL;
}
return true;
}
void lovrFilesystemDestroy() {

View File

@ -22,7 +22,7 @@ typedef struct {
vec_str_t requirePattern[2];
} FilesystemState;
void lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot);
bool lovrFilesystemInit(const char* argExe, const char* argGame, const char* argRoot);
void lovrFilesystemDestroy();
int lovrFilesystemCreateDirectory(const char* path);
int lovrFilesystemGetAppdataDirectory(char* dest, unsigned int size);

View File

@ -24,8 +24,9 @@ static void onResizeWindow(int width, int height) {
// Base
void lovrGraphicsInit(bool gammaCorrect) {
bool lovrGraphicsInit(bool gammaCorrect) {
state.gammaCorrect = gammaCorrect;
return false;
}
void lovrGraphicsDestroy() {

View File

@ -154,7 +154,7 @@ typedef struct {
} GraphicsState;
// Base
void lovrGraphicsInit(bool gammaCorrect);
bool lovrGraphicsInit(bool gammaCorrect);
void lovrGraphicsDestroy();
void lovrGraphicsPresent();
void lovrGraphicsSetWindow(WindowFlags* flags);

View File

@ -4,8 +4,8 @@
HeadsetInterface* lovrHeadsetDriver = NULL;
static bool initialized = false;
void lovrHeadsetInit(HeadsetDriver* drivers, int count, float offset, int msaa) {
if (initialized) return;
bool lovrHeadsetInit(HeadsetDriver* drivers, int count, float offset, int msaa) {
if (initialized) return false;
initialized = true;
for (int i = 0; i < count; i++) {
@ -37,6 +37,7 @@ void lovrHeadsetInit(HeadsetDriver* drivers, int count, float offset, int msaa)
}
lovrAssert(lovrHeadsetDriver, "No headset driver available, check t.headset.drivers in conf.lua");
return true;
}
void lovrHeadsetDestroy() {

View File

@ -110,5 +110,5 @@ extern HeadsetInterface lovrHeadsetOculusMobileDriver;
// Active driver
extern HeadsetInterface* lovrHeadsetDriver;
void lovrHeadsetInit(HeadsetDriver* drivers, int count, float offset, int msaa);
bool lovrHeadsetInit(HeadsetDriver* drivers, int count, float offset, int msaa);
void lovrHeadsetDestroy();

View File

@ -7,12 +7,12 @@
static MathState state;
void lovrMathInit() {
if (state.initialized) return;
bool lovrMathInit() {
if (state.initialized) return false;
state.generator = lovrRandomGeneratorCreate();
Seed seed = { .b64 = (uint64_t) time(0) };
lovrRandomGeneratorSetSeed(state.generator, seed);
state.initialized = true;
return state.initialized = true;
}
void lovrMathDestroy() {

View File

@ -9,7 +9,7 @@ typedef struct {
RandomGenerator* generator;
} MathState;
void lovrMathInit();
bool lovrMathInit();
void lovrMathDestroy();
RandomGenerator* lovrMathGetRandomGenerator();
void lovrMathOrientationToDirection(float angle, float ax, float ay, float az, vec3 v);

View File

@ -31,10 +31,10 @@ static void raycastCallback(void* data, dGeomID a, dGeomID b) {
static bool initialized = false;
void lovrPhysicsInit() {
if (initialized) return;
bool lovrPhysicsInit() {
if (initialized) return false;
dInitODE();
initialized = true;
return initialized = true;
}
void lovrPhysicsDestroy() {

View File

@ -85,7 +85,7 @@ typedef struct {
void* userdata;
} RaycastData;
void lovrPhysicsInit();
bool lovrPhysicsInit();
void lovrPhysicsDestroy();
World* lovrWorldCreate(float xg, float yg, float zg, bool allowSleep, const char** tags, int tagCount);

View File

@ -4,10 +4,10 @@
static ThreadState state;
void lovrThreadInit() {
if (state.initialized) return;
bool lovrThreadInit() {
if (state.initialized) return false;
map_init(&state.channels);
state.initialized = true;
return state.initialized = true;
}
void lovrThreadDeinit() {

View File

@ -22,7 +22,7 @@ typedef struct {
bool running;
} Thread;
void lovrThreadInit();
bool lovrThreadInit();
void lovrThreadDeinit();
struct Channel* lovrThreadGetChannel(const char* name);

View File

@ -4,10 +4,10 @@
static TimerState state;
void lovrTimerInit() {
if (state.initialized) return;
bool lovrTimerInit() {
if (state.initialized) return false;
lovrTimerDestroy();
state.initialized = true;
return state.initialized = true;
}
void lovrTimerDestroy() {

View File

@ -16,7 +16,7 @@ typedef struct {
int fps;
} TimerState;
void lovrTimerInit();
bool lovrTimerInit();
void lovrTimerDestroy();
double lovrTimerGetDelta();
double lovrTimerGetTime();