From ff2259841d650aee5368bb9b94405a70c7a706bc Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 11 Mar 2025 14:07:02 +0100 Subject: [PATCH 1/2] GH-130396: Work around for broken `pthread_get_stackaddr_np` on Emscripten Emscripten reports having `pthread_get_stackaddr_np` but it does nothing. I opened an upstream PR to actually fill in the stack information: https://github.com/emscripten-core/emscripten/pull/23887 Until we can update to an Emscripten version that includes this fix, we can work around it by using `#define`s to replace `pthread_get_stackaddr_np` with the modified version. --- Python/ceval.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/Python/ceval.c b/Python/ceval.c index 0a3b30513733bd..c692de16457312 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -346,6 +346,65 @@ _Py_EnterRecursiveCallUnchecked(PyThreadState *tstate) # define Py_C_STACK_SIZE 4000000 #endif +#if defined(__EMSCRIPTEN__) + +// Temporary workaround to make `pthread_getattr_np` work on Emscripten until a +// version of Emscripten is released containing the fix. +// https://github.com/emscripten-core/emscripten/pull/23887 + +#include "emscripten/stack.h" + +#define pthread_attr_t workaround_pthread_attr_t +#define pthread_getattr_np workaround_pthread_getattr_np +#define pthread_attr_getguardsize workaround_pthread_attr_getguardsize +#define pthread_attr_getstack workaround_pthread_attr_getstack +#define pthread_attr_destroy workaround_pthread_attr_destroy + +typedef struct { + void *_a_stackaddr; + size_t _a_stacksize, _a_guardsize; +} pthread_attr_t; + +extern __attribute__((__visibility__("hidden"))) unsigned __default_guardsize; + +// Modified version of pthread_getattr_np from the upstream PR. + +int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) { + attr->_a_stackaddr = (void*)emscripten_stack_get_base(); + attr->_a_stacksize = emscripten_stack_get_base() - emscripten_stack_get_end(); + attr->_a_guardsize = __default_guardsize; + return 0; +} + +// These three functions copied without any changes from Emscripten libc. + +int pthread_attr_getguardsize(const pthread_attr_t *restrict a, size_t *restrict size) +{ + *size = a->_a_guardsize; + return 0; +} + +int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict addr, size_t *restrict size) +{ +/// XXX musl is not standard-conforming? It should not report EINVAL if _a_stackaddr is zero, and it should +/// report EINVAL if a is null: http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_attr_getstack.html + if (!a) return EINVAL; +// if (!a->_a_stackaddr) +// return EINVAL; + + *size = a->_a_stacksize; + *addr = (void *)(a->_a_stackaddr - *size); + return 0; +} + +int pthread_attr_destroy(pthread_attr_t *a) +{ + return 0; +} + +#endif + + void _Py_InitializeRecursionLimits(PyThreadState *tstate) { From 297a53c06cd1e205f42c3ff30a289fb903dc3463 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 13 Mar 2025 13:10:01 +0100 Subject: [PATCH 2/2] Update comment --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index fa08c012c4ebac..8e785a16bc2278 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -367,8 +367,8 @@ _Py_EnterRecursiveCallUnchecked(PyThreadState *tstate) #if defined(__EMSCRIPTEN__) -// Temporary workaround to make `pthread_getattr_np` work on Emscripten until a -// version of Emscripten is released containing the fix. +// Temporary workaround to make `pthread_getattr_np` work on Emscripten. +// Emscripten 4.0.6 will contain a fix: // https://github.com/emscripten-core/emscripten/pull/23887 #include "emscripten/stack.h"