Skip to content

Commit ff22598

Browse files
committed
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: emscripten-core/emscripten#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.
1 parent 98fa4a4 commit ff22598

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

Python/ceval.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,65 @@ _Py_EnterRecursiveCallUnchecked(PyThreadState *tstate)
346346
# define Py_C_STACK_SIZE 4000000
347347
#endif
348348

349+
#if defined(__EMSCRIPTEN__)
350+
351+
// Temporary workaround to make `pthread_getattr_np` work on Emscripten until a
352+
// version of Emscripten is released containing the fix.
353+
// https://github.com/emscripten-core/emscripten/pull/23887
354+
355+
#include "emscripten/stack.h"
356+
357+
#define pthread_attr_t workaround_pthread_attr_t
358+
#define pthread_getattr_np workaround_pthread_getattr_np
359+
#define pthread_attr_getguardsize workaround_pthread_attr_getguardsize
360+
#define pthread_attr_getstack workaround_pthread_attr_getstack
361+
#define pthread_attr_destroy workaround_pthread_attr_destroy
362+
363+
typedef struct {
364+
void *_a_stackaddr;
365+
size_t _a_stacksize, _a_guardsize;
366+
} pthread_attr_t;
367+
368+
extern __attribute__((__visibility__("hidden"))) unsigned __default_guardsize;
369+
370+
// Modified version of pthread_getattr_np from the upstream PR.
371+
372+
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {
373+
attr->_a_stackaddr = (void*)emscripten_stack_get_base();
374+
attr->_a_stacksize = emscripten_stack_get_base() - emscripten_stack_get_end();
375+
attr->_a_guardsize = __default_guardsize;
376+
return 0;
377+
}
378+
379+
// These three functions copied without any changes from Emscripten libc.
380+
381+
int pthread_attr_getguardsize(const pthread_attr_t *restrict a, size_t *restrict size)
382+
{
383+
*size = a->_a_guardsize;
384+
return 0;
385+
}
386+
387+
int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict addr, size_t *restrict size)
388+
{
389+
/// XXX musl is not standard-conforming? It should not report EINVAL if _a_stackaddr is zero, and it should
390+
/// report EINVAL if a is null: http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_attr_getstack.html
391+
if (!a) return EINVAL;
392+
// if (!a->_a_stackaddr)
393+
// return EINVAL;
394+
395+
*size = a->_a_stacksize;
396+
*addr = (void *)(a->_a_stackaddr - *size);
397+
return 0;
398+
}
399+
400+
int pthread_attr_destroy(pthread_attr_t *a)
401+
{
402+
return 0;
403+
}
404+
405+
#endif
406+
407+
349408
void
350409
_Py_InitializeRecursionLimits(PyThreadState *tstate)
351410
{

0 commit comments

Comments
 (0)