diff --git a/src/api/l_event.c b/src/api/l_event.c index 1a792610..1a38d52b 100644 --- a/src/api/l_event.c +++ b/src/api/l_event.c @@ -1,5 +1,6 @@ #include "api.h" #include "event/event.h" +#include "thread/thread.h" #include "core/platform.h" #include "core/ref.h" #include @@ -105,7 +106,7 @@ static int nextEvent(lua_State* L) { case EVENT_THREAD_ERROR: luax_pushtype(L, Thread, event.data.thread.thread); lua_pushstring(L, event.data.thread.error); - free(event.data.thread.error); + lovrRelease(Thread, event.data.thread.thread); return 3; case EVENT_CUSTOM: diff --git a/src/api/l_thread_module.c b/src/api/l_thread_module.c index 2c96ade5..ff3ff7b4 100644 --- a/src/api/l_thread_module.c +++ b/src/api/l_thread_module.c @@ -13,10 +13,8 @@ static int threadRunner(void* data) { lovrRetain(thread); mtx_lock(&thread->lock); thread->running = true; - thread->error = NULL; mtx_unlock(&thread->lock); - // Lua state lua_State* L = luaL_newstate(); luaL_openlibs(L); lovrSetErrorCallback((errorFn*) luax_vthrow, L); @@ -27,23 +25,28 @@ static int threadRunner(void* data) { lua_pop(L, 2); if (luaL_loadbuffer(L, thread->body->data, thread->body->size, "thread") || lua_pcall(L, 0, 0, 0)) { - thread->error = lua_tostring(L, -1); + size_t length; + const char* error = lua_tolstring(L, -1, &length); + mtx_lock(&thread->lock); + thread->error = malloc(length + 1); + if (thread->error) { + memcpy(thread->error, error, length + 1); + lovrEventPush((Event) { + .type = EVENT_THREAD_ERROR, + .data.thread = { thread, thread->error } + }); + } + thread->running = false; + mtx_unlock(&thread->lock); + lovrRelease(Thread, thread); + lua_close(L); + return 1; } mtx_lock(&thread->lock); thread->running = false; mtx_unlock(&thread->lock); lovrRelease(Thread, thread); - - if (thread->error) { - lovrEventPush((Event) { - .type = EVENT_THREAD_ERROR, - .data.thread = { thread, strdup(thread->error) } - }); - lua_close(L); - return 1; - } - lua_close(L); return 0; } @@ -54,10 +57,13 @@ static int l_lovrThreadNewThread(lua_State* L) { size_t length; const char* str = lua_tolstring(L, 1, &length); if (memchr(str, '\n', MIN(1024, length))) { - blob = lovrBlobCreate(strdup(str), length, "thread code"); + void* data = malloc(length + 1); + lovrAssert(data, "Out of memory"); + memcpy(data, str, length + 1); + blob = lovrBlobCreate(data, length, "thread code"); } else { void* code = lovrFilesystemRead(str, -1, &length); - lovrAssert(code, "Could not read thread code from %s", str); + lovrAssert(code, "Could not read thread code from file '%s'", str); blob = lovrBlobCreate(code, length, str); } } else { diff --git a/src/modules/event/event.c b/src/modules/event/event.c index c9edc17e..75f92608 100644 --- a/src/modules/event/event.c +++ b/src/modules/event/event.c @@ -2,6 +2,7 @@ #include "platform.h" #include "core/arr.h" #include "core/ref.h" +#include "core/util.h" #include #include @@ -36,6 +37,10 @@ void lovrEventPump() { } void lovrEventPush(Event event) { + if (event.type == EVENT_THREAD_ERROR) { + lovrRetain(event.data.thread.thread); + } + arr_push(&state.events, event); } diff --git a/src/modules/headset/oculus_mobile.c b/src/modules/headset/oculus_mobile.c index 95d5cba3..dc7012eb 100644 --- a/src/modules/headset/oculus_mobile.c +++ b/src/modules/headset/oculus_mobile.c @@ -432,7 +432,10 @@ void bridgeLovrInit(BridgeLovrInitData *initData) { bridgeLovrMobileData.deviceType = initData->deviceType; free(apkPath); - apkPath = strdup(initData->apkPath); + size_t length = strlen(initData->apkPath); + apkPath = malloc(length + 1); + lovrAssert(apkPath, "Out of memory"); + memcpy(apkPath, initData->apkPath, length + 1); bridgeLovrInitState(); diff --git a/src/modules/thread/thread.c b/src/modules/thread/thread.c index 994afad7..46deace4 100644 --- a/src/modules/thread/thread.c +++ b/src/modules/thread/thread.c @@ -44,8 +44,6 @@ Thread* lovrThreadInit(Thread* thread, int (*runner)(void*), Blob* body) { lovrRetain(body); thread->runner = runner; thread->body = body; - thread->error = NULL; - thread->running = false; mtx_init(&thread->lock, mtx_plain); return thread; } @@ -55,6 +53,7 @@ void lovrThreadDestroy(void* ref) { mtx_destroy(&thread->lock); thrd_detach(thread->handle); lovrRelease(Blob, thread->body); + free(thread->error); } void lovrThreadStart(Thread* thread) { @@ -64,10 +63,9 @@ void lovrThreadStart(Thread* thread) { return; } - if (thrd_create(&thread->handle, thread->runner, thread) != thrd_success) { - lovrThrow("Could not create thread...sorry"); - return; - } + free(thread->error); + thread->error = NULL; + lovrAssert(thrd_create(&thread->handle, thread->runner, thread) == thrd_success, "Could not create thread...sorry"); } void lovrThreadWait(Thread* thread) { diff --git a/src/modules/thread/thread.h b/src/modules/thread/thread.h index 96fc4db8..78dfc8ff 100644 --- a/src/modules/thread/thread.h +++ b/src/modules/thread/thread.h @@ -11,7 +11,7 @@ typedef struct Thread { mtx_t lock; Blob* body; int (*runner)(void*); - const char* error; + char* error; bool running; } Thread;