@@ -366,6 +366,65 @@ _Py_EnterRecursiveCallUnchecked(PyThreadState *tstate)
366366# define Py_C_STACK_SIZE 4000000
367367#endif
368368
369+ #if defined(__EMSCRIPTEN__ )
370+
371+ // Temporary workaround to make `pthread_getattr_np` work on Emscripten.
372+ // Emscripten 4.0.6 will contain a fix:
373+ // https://github.com/emscripten-core/emscripten/pull/23887
374+
375+ #include "emscripten/stack.h"
376+
377+ #define pthread_attr_t workaround_pthread_attr_t
378+ #define pthread_getattr_np workaround_pthread_getattr_np
379+ #define pthread_attr_getguardsize workaround_pthread_attr_getguardsize
380+ #define pthread_attr_getstack workaround_pthread_attr_getstack
381+ #define pthread_attr_destroy workaround_pthread_attr_destroy
382+
383+ typedef struct {
384+ void * _a_stackaddr ;
385+ size_t _a_stacksize , _a_guardsize ;
386+ } pthread_attr_t ;
387+
388+ extern __attribute__((__visibility__ ("hidden" ))) unsigned __default_guardsize ;
389+
390+ // Modified version of pthread_getattr_np from the upstream PR.
391+
392+ int pthread_getattr_np (pthread_t thread , pthread_attr_t * attr ) {
393+ attr -> _a_stackaddr = (void * )emscripten_stack_get_base ();
394+ attr -> _a_stacksize = emscripten_stack_get_base () - emscripten_stack_get_end ();
395+ attr -> _a_guardsize = __default_guardsize ;
396+ return 0 ;
397+ }
398+
399+ // These three functions copied without any changes from Emscripten libc.
400+
401+ int pthread_attr_getguardsize (const pthread_attr_t * restrict a , size_t * restrict size )
402+ {
403+ * size = a -> _a_guardsize ;
404+ return 0 ;
405+ }
406+
407+ int pthread_attr_getstack (const pthread_attr_t * restrict a , void * * restrict addr , size_t * restrict size )
408+ {
409+ /// XXX musl is not standard-conforming? It should not report EINVAL if _a_stackaddr is zero, and it should
410+ /// report EINVAL if a is null: http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_attr_getstack.html
411+ if (!a ) return EINVAL ;
412+ // if (!a->_a_stackaddr)
413+ // return EINVAL;
414+
415+ * size = a -> _a_stacksize ;
416+ * addr = (void * )(a -> _a_stackaddr - * size );
417+ return 0 ;
418+ }
419+
420+ int pthread_attr_destroy (pthread_attr_t * a )
421+ {
422+ return 0 ;
423+ }
424+
425+ #endif
426+
427+
369428void
370429_Py_InitializeRecursionLimits (PyThreadState * tstate )
371430{
0 commit comments