fix memory leaking and thread sync problems
This commit is contained in:
@@ -5413,6 +5413,8 @@ JSC_SCALL(io_slurp,
|
||||
PHYSFS_close(f);
|
||||
ret = JS_NewStringLen(js,data, stat.filesize);
|
||||
|
||||
free(data);
|
||||
|
||||
END:
|
||||
)
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <SDL3/SDL_atomic.h>
|
||||
|
||||
#define WOTA_IMPLEMENTATION
|
||||
#include "wota.h"
|
||||
#include "qjs_wota.h"
|
||||
@@ -46,6 +48,9 @@ static struct { char *key; prosperon_rt *value; } *actors = NULL;
|
||||
static unsigned char *zip_buffer_global = NULL;
|
||||
static char *prosperon = NULL;
|
||||
|
||||
static SDL_AtomicInt shutdown;
|
||||
static SDL_Thread **runners = NULL;
|
||||
|
||||
static void set_actor_state(prosperon_rt *actor);
|
||||
|
||||
static Uint32 actor_remove_cb(prosperon_rt *actor, Uint32 id, Uint32 interval)
|
||||
@@ -437,8 +442,10 @@ void actor_free(prosperon_rt *actor)
|
||||
JS_FreeContext(js);
|
||||
JS_FreeRuntime(rt);
|
||||
free(actor->id);
|
||||
|
||||
|
||||
SDL_UnlockMutex(actor->mutex);
|
||||
SDL_DestroyMutex(actor->mutex);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
SDL_DestroyMutex(actor->msg_mutex);
|
||||
|
||||
free(actor);
|
||||
@@ -450,22 +457,26 @@ void actor_free(prosperon_rt *actor)
|
||||
/* Timer callback adds an event to the queue under evt_mutex. */
|
||||
Uint32 actor_timer_cb(prosperon_rt *actor, SDL_TimerID id, Uint32 interval)
|
||||
{
|
||||
int idx = hmgeti(actor->timers, id);
|
||||
if (idx == -1) return 0;
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
int idx = hmgeti(actor->timers, id);
|
||||
if (idx == -1) goto END;
|
||||
|
||||
JSValue cb = actor->timers[idx].value;
|
||||
hmdel(actor->timers, id);
|
||||
arrput(actor->events, cb);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
|
||||
set_actor_state(actor);
|
||||
return interval;
|
||||
|
||||
END:
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* JS function that schedules a timer. */
|
||||
JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
if (!JS_IsFunction(js, argv[0]))
|
||||
return JS_ThrowReferenceError(js, "Argument must be a function.");
|
||||
|
||||
prosperon_rt *actor = JS_GetContextOpaque(js);
|
||||
double seconds;
|
||||
JS_ToFloat64(js, &seconds, argv[1]);
|
||||
@@ -473,7 +484,8 @@ JSValue js_actor_delay(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
Uint32 id = SDL_AddTimerNS(ns, actor_timer_cb, actor);
|
||||
|
||||
SDL_LockMutex(actor->msg_mutex);
|
||||
hmput(actor->timers, id, JS_DupValue(js, argv[0]));
|
||||
JSValue cb = JS_DupValue(js, argv[0]);
|
||||
hmput(actor->timers, id, cb);
|
||||
SDL_UnlockMutex(actor->msg_mutex);
|
||||
|
||||
return JS_UNDEFINED;
|
||||
@@ -533,9 +545,10 @@ void script_startup(prosperon_rt *prt)
|
||||
}
|
||||
PHYSFS_Stat stat;
|
||||
PHYSFS_stat(ENGINE, &stat);
|
||||
void *data = malloc(stat.filesize);
|
||||
char *data = malloc(stat.filesize+1);
|
||||
PHYSFS_readBytes(eng, data, stat.filesize);
|
||||
PHYSFS_close(eng);
|
||||
data[stat.filesize] = 0;
|
||||
|
||||
/* Called with actor->mutex locked by create_actor(). */
|
||||
JSValue v = JS_Eval(js, data, (size_t)stat.filesize, ENGINE, JS_EVAL_FLAG_STRICT);
|
||||
@@ -601,7 +614,7 @@ void script_evalf(JSContext *js, const char *format, ...)
|
||||
|
||||
static int crank_actor(void *data)
|
||||
{
|
||||
while (true) {
|
||||
while (!SDL_GetAtomicInt(&shutdown)) {
|
||||
SDL_LockMutex(queue_mutex);
|
||||
prosperon_rt *actor = NULL;
|
||||
if (arrlen(ready_queue) > 0) {
|
||||
@@ -636,6 +649,7 @@ static void signal_handler(int sig)
|
||||
JSContext *js = main->context;
|
||||
script_evalf(js, "prosperon.dispatch('%s')", str);
|
||||
}
|
||||
SDL_Quit();
|
||||
if (sig == SIGTERM || sig == SIGINT) exit(1);
|
||||
}
|
||||
|
||||
@@ -646,6 +660,14 @@ static void exit_handler(void)
|
||||
JSContext *js = main->context;
|
||||
script_evalf(js, "prosperon.dispatch('exit')");
|
||||
}
|
||||
|
||||
SDL_SetAtomicInt(&shutdown, 1);
|
||||
int status;
|
||||
SDL_BroadcastCondition(queue_cond);
|
||||
for (int i = 0; i < arrlen(runners); i++)
|
||||
SDL_WaitThread(runners[i], &status);
|
||||
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// Assume these helper functions exist or need to be implemented
|
||||
@@ -1257,6 +1279,8 @@ static WotaBuffer event2wota(const SDL_Event *event) {
|
||||
return wb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
|
||||
@@ -1295,7 +1319,7 @@ int main(int argc, char **argv)
|
||||
/* Start the thread that pumps ready actors, one per logical core. */
|
||||
for (int i = 0; i < cores; i++) {
|
||||
SDL_Thread *thread = SDL_CreateThread(crank_actor, "actor_runner", NULL);
|
||||
SDL_DetachThread(thread);
|
||||
arrput(runners,thread);
|
||||
}
|
||||
|
||||
/* Set up signal and exit handlers. */
|
||||
|
||||
Reference in New Issue
Block a user