From 4079e68259b444c7c3e804f4924fd701f41236e6 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Sat, 15 Feb 2025 14:20:25 +0100 Subject: [PATCH 1/2] Clean up thread registration code and disable usage of DllMain based thread registration on Windows. --- libs/mod_neko/mod_neko.c | 6 ---- vm/alloc.c | 16 ++-------- vm/threads.c | 68 ++-------------------------------------- 3 files changed, 5 insertions(+), 85 deletions(-) diff --git a/libs/mod_neko/mod_neko.c b/libs/mod_neko/mod_neko.c index 62ccb900..f4a484a1 100644 --- a/libs/mod_neko/mod_neko.c +++ b/libs/mod_neko/mod_neko.c @@ -185,14 +185,8 @@ static int neko_handler_rec( request_rec *r ) { const char *ctype; value exc = NULL; -/* - Seems to crash on Windows. And on Linux, we rarely have libGC 7.x installed anyway - -# if defined(APACHE_2_X) || defined(NEKO_WINDOWS) // we are using threads, so let's make sure that the current thread is registered neko_thread_register(true); -# endif -*/ config.hits++; diff --git a/vm/alloc.c b/vm/alloc.c index 8a3986af..c7ae77da 100644 --- a/vm/alloc.c +++ b/vm/alloc.c @@ -117,21 +117,11 @@ static void null_warn_proc( char *msg, int arg ) { } void neko_gc_init() { -# ifndef NEKO_WINDOWS - // we can't set this on windows with old GC since - // it's already initialized through its own DllMain - GC_all_interior_pointers = 0; -# endif -#if (GC_VERSION_MAJOR >= 7) && defined(NEKO_WINDOWS) - GC_all_interior_pointers = 0; -# ifndef NEKO_STANDALONE - GC_use_DllMain(); // needed to auto-detect threads created by Apache -# endif -#endif - GC_java_finalization = 1; + GC_set_all_interior_pointers(0); + GC_set_java_finalization(1); GC_init(); GC_set_warn_proc((GC_warn_proc)(void*)null_warn_proc); - GC_no_dls = 1; + GC_set_no_dls(1); #ifdef LOW_MEM GC_dont_expand = 1; #endif diff --git a/vm/threads.c b/vm/threads.c index 524d9ac8..516abdf9 100644 --- a/vm/threads.c +++ b/vm/threads.c @@ -19,10 +19,6 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#ifdef __APPLE__ -// prevent later redefinition of bool -# include -#endif #include "vm.h" #include @@ -69,10 +65,6 @@ struct _mt_lock { pthread_mutex_t lock; }; -// should be enough to store any GC_stack_base -// implementation -typedef char __stack_base[64]; - #endif #endif // !NEKO_THREADS @@ -166,52 +158,20 @@ EXTERN int neko_thread_create( thread_main_func init, thread_main_func main, voi # endif } -#if defined(NEKO_POSIX) && defined(NEKO_THREADS) -# include - typedef void (*callb_func)( thread_main_func, void * ); - typedef int (*std_func)(); - typedef int (*gc_stack_ptr)( __stack_base * ); - -static int do_nothing( __stack_base *sb ) { - return -1; -} - -#endif - EXTERN void neko_thread_blocking( thread_main_func f, void *p ) { # if !defined(NEKO_THREADS) f(p); // nothing # elif defined(NEKO_WINDOWS) f(p); // we don't have pthreads issues # else - // we have different APIs depending on the GC version, make sure we load - // the good one at runtime - static callb_func do_blocking = NULL; - static std_func start = NULL, end = NULL; - if( do_blocking ) - do_blocking(f,p); - else if( start ) { - start(); - f(p); - end(); - } else { - void *self = dlopen(NULL,0); - do_blocking = (callb_func)dlsym(self,"GC_do_blocking"); - if( !do_blocking ) { - start = (std_func)dlsym(self,"GC_start_blocking"); - end = (std_func)dlsym(self,"GC_end_blocking"); - if( !start || !end ) - val_throw(alloc_string("Could not init GC blocking API")); - } - neko_thread_blocking(f,p); - } + GC_do_blocking((GC_fn_type)f, p); # endif } EXTERN bool neko_thread_register( bool t ) { # if !defined(NEKO_THREADS) return 0; -# elif defined(NEKO_WINDOWS) +# else struct GC_stack_base sb; int r; if( !t ) @@ -220,30 +180,6 @@ EXTERN bool neko_thread_register( bool t ) { return 0; r = GC_register_my_thread(&sb); return( r == GC_SUCCESS || r == GC_DUPLICATE ); -# else - // since the API is only available on GC 7.0, - // we will do our best to locate it dynamically - static gc_stack_ptr get_sb = NULL, my_thread = NULL; - static std_func unreg_my_thread = NULL; - if( !t && unreg_my_thread != NULL ) { - return unreg_my_thread() == GC_SUCCESS; - } else if( my_thread != NULL ) { - __stack_base sb; - int r; - if( get_sb(&sb) != GC_SUCCESS ) - return 0; - r = my_thread(&sb); - return( r == GC_SUCCESS || r == GC_DUPLICATE ); - } else { - void *self = dlopen(NULL,0); - my_thread = (gc_stack_ptr)dlsym(self,"GC_register_my_thread"); - get_sb = (gc_stack_ptr)dlsym(self,"GC_get_stack_base"); - unreg_my_thread = (std_func)dlsym(self,"GC_unregister_my_thread"); - if( my_thread == NULL ) my_thread = do_nothing; - if( get_sb == NULL ) get_sb = do_nothing; - if( unreg_my_thread == NULL ) unreg_my_thread = (std_func)do_nothing; - return neko_thread_register(t); - } # endif } From b37c589a5a153aac061602fa3c24091d6cf24612 Mon Sep 17 00:00:00 2001 From: Apprentice-Alchemist <53486764+Apprentice-Alchemist@users.noreply.github.com> Date: Sat, 15 Feb 2025 16:12:03 +0100 Subject: [PATCH 2/2] [mod_neko] Make sure thread is unregistered. --- libs/mod_neko/mod_neko.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/mod_neko/mod_neko.c b/libs/mod_neko/mod_neko.c index f4a484a1..0ab21f0b 100644 --- a/libs/mod_neko/mod_neko.c +++ b/libs/mod_neko/mod_neko.c @@ -185,9 +185,6 @@ static int neko_handler_rec( request_rec *r ) { const char *ctype; value exc = NULL; - // we are using threads, so let's make sure that the current thread is registered - neko_thread_register(true); - config.hits++; ctx.r = r; @@ -304,11 +301,14 @@ static int neko_handler( request_rec *r ) { int ret; if( strcmp(r->handler,"neko-handler") != 0) return DECLINED; + + neko_thread_register(true); if( config.use_stats ) neko_stats_measure(NULL,r->hostname,1); ret = neko_handler_rec(r); neko_vm_select(NULL); if( config.use_stats ) neko_stats_measure(NULL,r->hostname,0); gc_major(); + neko_thread_register(false); return ret; }