]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-130396: Work around for broken `pthread_get_stackaddr_np` on Emscripten (#131088)
authorHood Chatham <roberthoodchatham@gmail.com>
Thu, 13 Mar 2025 23:04:40 +0000 (00:04 +0100)
committerGitHub <noreply@github.com>
Thu, 13 Mar 2025 23:04:40 +0000 (07:04 +0800)
Implements a workaround implementation of `pthread_get_stackaddr_np` for Emscripten.
This will be replaced by an implementation that will be included in Emscripten 4.0.6.

Python/ceval.c

index 34f4417f5fc4871a19f11aab5a35155a57ee0e1b..1720fff104030d95a201ed66eeb3cc8383968be3 100644 (file)
@@ -366,6 +366,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.
+// Emscripten 4.0.6 will contain a 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)
 {