aboutsummaryrefslogtreecommitdiff
path: root/src/thread.c
diff options
context:
space:
mode:
authorame <[email protected]>2024-05-09 10:31:26 -0500
committerame <[email protected]>2024-05-09 10:31:26 -0500
commit2b985e277f06a7086025ab292ddb22b5ded89189 (patch)
tree406d0e6dc1a7a525b4dd0be05b1fc35a2dd8de4a /src/thread.c
parentc562d0f9e336251f9ff599a840310835820b0461 (diff)
work on memory saftey
Diffstat (limited to 'src/thread.c')
-rw-r--r--src/thread.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/src/thread.c b/src/thread.c
index 441793b..393d3fb 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -13,14 +13,15 @@
struct thread_info {
str* function;
lua_State* L;
- int return_count;
+ int return_count, done;
pthread_t tid;
- pthread_cond_t cond;
pthread_mutex_t lock;
};
#include "io.h"
+//give the current thread priority to locking thread_lock_lock (fixes race conds)
+pthread_mutex_t thread_priority_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t thread_lock_lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
larray_t* thread_locks = NULL;
@@ -28,6 +29,8 @@ int l_tlock(lua_State* L){
int idx = luaL_checkinteger(L, 1);
pthread_mutex_lock(&thread_lock_lock);
+ pthread_mutex_lock(&thread_priority_lock);
+ pthread_mutex_unlock(&thread_priority_lock);
pthread_mutex_t mutex;
if(thread_locks == NULL) thread_locks = larray_init();
int i = 0;
@@ -37,9 +40,13 @@ int l_tlock(lua_State* L){
larray_set(&thread_locks, idx, (void*)mutex);
} else {
pthread_mutex_t m = (pthread_mutex_t)thread_locks->arr[i].value;
+ pthread_mutex_lock(&thread_priority_lock);
+
pthread_mutex_unlock(&thread_lock_lock);
pthread_mutex_lock(&m);
pthread_mutex_lock(&thread_lock_lock);
+
+ pthread_mutex_unlock(&thread_priority_lock);
thread_locks->arr[i].value = (void*)m;
}
@@ -90,6 +97,7 @@ int l_res(lua_State* L){
void* handle_thread(void* _args){
struct thread_info* args = (struct thread_info*)_args;
lua_State* L = args->L;
+ lua_gc(L, LUA_GCSTOP);
lua_newtable(L);
int res_idx = lua_gettop(L);
@@ -117,20 +125,37 @@ int l_await(lua_State* L){
lua_gettable(L, 1);
struct thread_info* info = lua_touserdata(L, -1);
- pthread_mutex_lock(&info->lock);
+ if(info->L == NULL) p_fatal("thread has already been cleaned");
+ if(!info->done) pthread_mutex_lock(&info->lock);
+ info->done = 1;
for(int i = 0; i != info->return_count; i++){
int ot = lua_gettop(info->L);
lua_pushvalue(info->L, ot - info->return_count + i);
i_dcopy(info->L, L, NULL);
-
+
lua_settop(info->L, ot);
}
return info->return_count;
}
+int l_clean(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ struct thread_info* info = lua_touserdata(L, -1);
+ if(info->L != NULL){
+ lua_gc(info->L, LUA_GCRESTART);
+ lua_gc(info->L, LUA_GCCOLLECT);
+ lua_close(info->L);
+ info->L = NULL;
+ pthread_mutex_destroy(&info->lock);
+ free(info);
+ }
+ return 0;
+}
+
int l_async(lua_State* oL){
lua_State* L = luaL_newstate();
@@ -142,7 +167,6 @@ int l_async(lua_State* oL){
struct thread_info* args = calloc(1, sizeof * args);
args->L = L;
- args->cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
args->lock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&args->lock);
args->return_count = 0;
@@ -157,7 +181,15 @@ int l_async(lua_State* oL){
lua_newtable(oL);
int res_idx = lua_gettop(oL);
luaI_tsetcf(oL, res_idx, "await", l_await);
+ luaI_tsetcf(oL, res_idx, "clean", l_clean);
luaI_tsetlud(oL, res_idx, "_", args);
+
+ lua_newtable(oL);
+ int meta_idx = lua_gettop(oL);
+ luaI_tsetcf(oL, meta_idx, "__gc", l_clean);
+
+ lua_pushvalue(oL, meta_idx);
+ lua_setmetatable(oL, res_idx);
lua_pushvalue(oL, res_idx);
return 1;
}