diff --git a/rktwebview.cpp b/rktwebview.cpp index 2073aa0..7dcf49b 100644 --- a/rktwebview.cpp +++ b/rktwebview.cpp @@ -87,6 +87,7 @@ typedef struct { std::string log_file; void (*evt_cb)(int entries); + std::mutex evt_cb_mutex; MemQueue *evt_queue; std::thread *guard_thread; bool guard_go_on; @@ -226,6 +227,8 @@ bool runRktWebview(Handle_t *handler) #define EVT_GUARD_STOP -93273 #define EVT_ALIVE_ERROR -94328 +#define EVT_NULL -95372 + #define WAIT_ON_EVENT_MS (2 * 1000) #define ALIVE_MESSAGE_INTERVAL_S 5 // Should be smaller than 10 seconds #define MAX_WAIT_RESULT (2 * 1000) // Maximum wait in milliseconds for a result per time @@ -241,15 +244,20 @@ void rkt_evt_guard(void) if (handler->verbose) { INFO2("Got event wv = %d, %s\n", wv, data.c_str()); } - if (wv != EVT_GUARD_STOP) { + if (wv != EVT_GUARD_STOP && wv != EVT_NULL) { handler->evt_queue->enqueue(wv, data); + handler->evt_cb_mutex.lock(); if (handler->evt_cb != nullptr) { // evt_cb could be cleared to null INFO2("Calling evt_cb with %d, %s\n", wv, data.c_str()); + handler->evt_cb(1); INFO0("done\n"); } else { INFO0("evt_cb = null\n"); } + handler->evt_cb_mutex.unlock(); + } else if (wv == EVT_NULL) { + INFO0("Got NULL message (evt_guard)\n"); } else { INFO0("Got stop message (evt_guard)\n"); handler->guard_go_on = false; @@ -261,6 +269,7 @@ void rkt_evt_guard(void) } } INFO0("Leaving rkt_evt_guard\n"); + } @@ -303,9 +312,15 @@ void rkt_webview_cleanup() INFO0("rkt_webview_cleanup - cleaning up\n"); handler->verbose = true; + handler->event_queue->enqueue(EVT_NULL); + //sleep_ms(1000); // Why is this second so important? + // I just don't get why the evt_guard thread is blocking and getting core dumped + // on the thread join, if this second is not given + // (to racket?). if (handler->valid) { if (handler->guard_thread != nullptr) { + handler->evt_cb_mutex.lock(); if (handler->evt_cb != nullptr) { INFO0("Clearing evt_guard callback to null\n"); handler->evt_cb = nullptr; @@ -314,6 +329,7 @@ void rkt_webview_cleanup() } INFO0("Stopping evt_guard (enqueuing evt_guard_stop)\n"); handler->event_queue->enqueue(EVT_GUARD_STOP); + handler->evt_cb_mutex.unlock(); INFO0("yielding current thread and hopefully activating evt_guard thread\n"); YIELD(); INFO0("joining guard thread\n"); @@ -449,14 +465,25 @@ static inline bool validHandle() #define FAIL_CALL_JS if (!validHandle()) { return nullptr; } #define FAIL_INFO FAIL_CALL_JS -void rkt_webview_register_evt_callback(void (*f)(int)) +int rkt_webview_register_evt_callback(void (*f)(int)) { RKT_WEBVIEW_INIT; - handler->evt_cb = f; - if (handler->guard_thread == nullptr) { - handler->guard_go_on = true; - handler->guard_thread = new std::thread(rkt_evt_guard); + if (handler->evt_cb_mutex.try_lock()) { + INFO1("registering callback %p\n", f); + + handler->evt_cb = f; + if (handler->guard_thread == nullptr) { + handler->guard_go_on = true; + handler->guard_thread = new std::thread(rkt_evt_guard); + INFO0("guard thread started\n"); + } + + handler->evt_cb_mutex.unlock(); + return 1; + } else { + WARN1("Cannot aquire lock for registering callback %p\n", f); + return 0; } } diff --git a/rktwebview.h b/rktwebview.h index 96de054..20be273 100644 --- a/rktwebview.h +++ b/rktwebview.h @@ -14,7 +14,7 @@ RKTWEBVIEW_EXPORT void rkt_webview_env(const char *env_cmds[]); RKTWEBVIEW_EXPORT void rkt_webview_init(const char *from); RKTWEBVIEW_EXPORT void rkt_webview_cleanup(); RKTWEBVIEW_EXPORT void rkt_webview_exit_done(int done); -RKTWEBVIEW_EXPORT void rkt_webview_register_evt_callback(void (*f)(int)); +RKTWEBVIEW_EXPORT int rkt_webview_register_evt_callback(void (*f)(int)); RKTWEBVIEW_EXPORT void rkt_webview_set_loglevel(rkt_webview_loglevel_t l); RKTWEBVIEW_EXPORT rkt_data_t *rkt_webview_info();