diff options
| author | amelia squires <[email protected]> | 2025-10-14 21:46:38 -0500 |
|---|---|---|
| committer | amelia squires <[email protected]> | 2025-10-14 21:46:38 -0500 |
| commit | af09c42e8067dfc832f7e1dce92860e1022c75fa (patch) | |
| tree | a444ec4586f9b1c54ea6680ffee2dc940644427d | |
| parent | a67dc94484cf9869793fc1861914b800a6559a74 (diff) | |
tons of thread changed, more testing needed
| -rw-r--r-- | library/lullaby/thread.lua | 7 | ||||
| -rw-r--r-- | makefile | 3 | ||||
| -rw-r--r-- | src/net.c | 1 | ||||
| -rw-r--r-- | src/thread.c | 60 | ||||
| -rw-r--r-- | src/thread.h | 4 | ||||
| -rw-r--r-- | tests/kill.lua | 15 | ||||
| -rw-r--r-- | tests/tests.lua | 1 |
7 files changed, 83 insertions, 8 deletions
diff --git a/library/lullaby/thread.lua b/library/lullaby/thread.lua index 6015a0b..f529049 100644 --- a/library/lullaby/thread.lua +++ b/library/lullaby/thread.lua @@ -16,11 +16,16 @@ function async.await(T) end ---@return nil function async.clean(T) end ----stops the thread +---stops the thread, may be unavaliable on some systems (android) and will call async:kill instead ---@param T async-table ---@return nil function async.close(T) end +---stops the thread forcefully, may cause problems +---@param T async-table +---@return nil +function async.kill(T) end + ---contains data for the thread ---@deprecated ---@type lightuserdata @@ -57,6 +57,9 @@ debug: all san: CFLAGS += -ggdb3 -static-libasan -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls
san: all
+tsan: CFLAGS += -ggdb3 -static-libasan -fsanitize=undefined -fsanitize=thread -fno-omit-frame-pointer -fno-optimize-sibling-calls
+tsan: all
+
reg:
rm src/reg.o
@@ -928,7 +928,6 @@ net_end: lua_close(L);
threads--;
- printf("out\n");
return NULL;
}
diff --git a/src/thread.c b/src/thread.c index b113915..da4bcb5 100644 --- a/src/thread.c +++ b/src/thread.c @@ -3,6 +3,7 @@ #include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
+#include <signal.h>
#include "types/str.h"
#include "util.h"
@@ -15,7 +16,7 @@ struct thread_info { lua_State* L;
int return_count, done;
pthread_t tid;
- pthread_mutex_t* lock;
+ pthread_mutex_t* lock, *ready_lock;
};
#include "io.h"
@@ -168,11 +169,23 @@ int l_res(lua_State* L){ return 1;
}
+void _thread_exit_signal(int i){
+ pthread_exit(NULL);
+}
+
void* handle_thread(void* _args){
struct thread_info* args = (struct thread_info*)_args;
lua_State* L = args->L;
+ pthread_mutex_lock(&*args->lock);
+
+#ifdef SUPPORTS_PTHREAD_CANCEL
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+#endif
+
pthread_detach(args->tid);
+ signal(SIGUSR1, _thread_exit_signal);
+
+ pthread_mutex_unlock(&*args->ready_lock);
lua_newtable(L);
int res_idx = lua_gettop(L);
@@ -202,9 +215,11 @@ int _thread_await(lua_State* L){ lua_pushstring(L, "_");
lua_gettable(L, 1);
struct thread_info* info = lua_touserdata(L, -1);
-
if(info->L == NULL) luaI_error(L, -1, "thread was already closed")
- if(!info->done) pthread_mutex_lock(&*info->lock);
+ //maybe error here if tid is zero
+ if(!info->done && info->tid != 0){
+ pthread_mutex_lock(&*info->lock);
+ }
info->done = 1;
env_table(info->L, 0);
@@ -245,6 +260,14 @@ int _thread_clean(lua_State* L){ if(info != NULL && info->L != NULL){
luaI_tsetnil(L, 1, "_");
+ if(info->tid != 0){
+#ifdef SUPPORTS_PTHREAD_CANCEL
+ pthread_cancel(info->tid);
+#else
+ pthread_kill(info->tid, SIGUSR1);
+#endif
+ }
+
//lua_gc(info->L, LUA_GCRESTART);
lua_gc(info->L, LUA_GCCOLLECT);
@@ -254,18 +277,37 @@ int _thread_clean(lua_State* L){ pthread_mutex_destroy(&*info->lock);
free(info->lock);
- pthread_cancel(info->tid);
+
free(info);
}
return 0;
}
+
int _thread_close(lua_State* L){
+#ifdef SUPPORTS_PTHREAD_CANCEL
+
lua_pushstring(L, "_");
lua_gettable(L, 1);
struct thread_info* info = lua_touserdata(L, -1);
pthread_cancel(info->tid);
+ info->tid = 0;
+
+ return 0;
+#else
+ return _thread_kill(L);
+#endif
+}
+
+
+int _thread_kill(lua_State* L){
+ lua_pushstring(L, "_");
+ lua_gettable(L, 1);
+ struct thread_info* info = lua_touserdata(L, -1);
+
+ pthread_kill(info->tid, SIGUSR1);
+ info->tid = 0;
return 0;
}
@@ -280,20 +322,28 @@ int l_async(lua_State* oL){ struct thread_info* args = calloc(1, sizeof * args);
args->L = L;
args->lock = malloc(sizeof * args->lock);
+ args->ready_lock = malloc(sizeof * args->ready_lock);
pthread_mutex_init(&*args->lock, NULL);
- pthread_mutex_lock(&*args->lock);
+ pthread_mutex_init(&*args->ready_lock, NULL);
args->return_count = 0;
args->function = str_init("");
lua_pushvalue(oL, 1);
lua_dump(oL, writer, (void*)args->function, 0);
+ pthread_mutex_lock(&*args->ready_lock);
pthread_create(&args->tid, NULL, handle_thread, (void*)args);
+ pthread_mutex_lock(&*args->ready_lock);
+
+ pthread_mutex_unlock(&*args->ready_lock);
+ pthread_mutex_destroy(&*args->ready_lock);
+ free(args->ready_lock);
lua_newtable(oL);
int res_idx = lua_gettop(oL);
luaI_tsetcf(oL, res_idx, "await", _thread_await);
luaI_tsetcf(oL, res_idx, "clean", _thread_clean);
+ luaI_tsetcf(oL, res_idx, "kill", _thread_kill);
luaI_tsetcf(oL, res_idx, "close", _thread_close);
luaI_tsetlud(oL, res_idx, "_", args);
diff --git a/src/thread.h b/src/thread.h index 0b3a27d..4fa0e04 100644 --- a/src/thread.h +++ b/src/thread.h @@ -1,6 +1,10 @@ #include "lua.h"
#include "config.h"
+#ifndef __ANDROID__
+#define SUPPORTS_PTHREAD_CANCEL
+#endif
+
int l_async(lua_State*);
int l_tlock(lua_State*);
int l_tunlock(lua_State*);
diff --git a/tests/kill.lua b/tests/kill.lua new file mode 100644 index 0000000..53344dc --- /dev/null +++ b/tests/kill.lua @@ -0,0 +1,15 @@ +local llby = require"lullaby" + +local t = llby.thread.async(function(res) + for i = 1, 50 do + print(i) + os.execute("sleep 1") + end +end) + +os.execute("sleep 5") + +print("killing") +t:close() +t:await() +print("after kill") diff --git a/tests/tests.lua b/tests/tests.lua index 6dae570..39c4d12 100644 --- a/tests/tests.lua +++ b/tests/tests.lua @@ -20,7 +20,6 @@ end local handle = assert(io.popen("find tests/units/".. search .." -type f")) for file in handle:lines() do - print(_G._locals) total = total + 1 local f = loadfile(file)() |
