Skip to content

Commit d701f8e

Browse files
authored
gh-145177: Bump Emscripten to 6.0.0 (#151611)
Bumps Emscripten to 6.0.0, and fixes related issues in getentropy() and umask().
1 parent 17720b1 commit d701f8e

5 files changed

Lines changed: 56 additions & 14 deletions

File tree

Lib/test/test_platform.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,20 @@ def test_ios_ver(self):
534534

535535
def test_libc_ver(self):
536536
if support.is_emscripten:
537-
assert platform.libc_ver() == ("emscripten", "4.0.19")
537+
import tomllib
538+
from pathlib import Path
539+
540+
# Get expected emscripten version from emscripten config
541+
config_path = (
542+
Path(__file__).parents[2] / "Platforms/emscripten/config.toml"
543+
)
544+
with open(config_path, "rb") as fp:
545+
emscripten_version = tomllib.load(fp)["emscripten-version"]
546+
547+
self.assertEqual(
548+
platform.libc_ver(), ("emscripten", emscripten_version)
549+
)
550+
538551
return
539552
# check that libc_ver(executable) doesn't raise an exception
540553
if os.path.isdir(sys.executable) and \

Platforms/emscripten/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Any data that can vary between Python versions is to be kept in this file.
22
# This allows for blanket copying of the Emscripten build code between supported
33
# Python versions.
4-
emscripten-version = "4.0.19"
4+
emscripten-version = "6.0.0"
55
node-version = "24"
66
test-args = [
77
"-m", "test",

Python/emscripten_syscalls.c

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,27 @@ int __syscall_getuid32(void) {
2323
return __syscall_getuid32_js();
2424
}
2525

26-
EM_JS(int, __syscall_umask_js, (int mask), {
27-
// If we're in node and we can, call native process.umask()
26+
// Emscripten's syscall layer tracks the umask in SYSCALLS.currentUmask and
27+
// applies it itself when creating files and directories. We mount the real
28+
// filesystem via NODEFS, which applies proces.umask() to everything as well. To
29+
// avoid masking the mode twice, read and zero out process umask at startup,
30+
// and store it as emscripten's umask.
31+
EM_JS(void, __syscall_init_umask_js, (void), {
2832
if (ENVIRONMENT_IS_NODE) {
2933
try {
30-
return process.umask(mask);
31-
} catch(e) {
32-
// oops...
33-
// NodeJS docs: "In Worker threads, process.umask(mask) will throw an exception."
34-
// umask docs: "This system call always succeeds"
35-
return 0;
34+
// process.umask(0) returns the previous umask and sets it to 0.
35+
SYSCALLS.currentUmask = process.umask(0);
36+
} catch (e) {
37+
// NodeJS docs: "In Worker threads, process.umask(mask) will throw an
38+
// exception." In that case just keep emscripten's default umask.
3639
}
3740
}
38-
// Fall back to the stub case of returning 0.
39-
return 0;
4041
})
4142

42-
int __syscall_umask(int mask) {
43-
return __syscall_umask_js(mask);
43+
EM_JS_DEPS(__syscall_init_umask, "$SYSCALLS");
44+
45+
__attribute__((constructor)) void __syscall_init_umask(void) {
46+
__syscall_init_umask_js();
4447
}
4548

4649
#include <wasi/api.h>
@@ -290,6 +293,26 @@ int __syscall_poll(intptr_t fds, int nfds, int timeout) {
290293
return __block_for_int(p);
291294
}
292295

296+
297+
// Workaround for an Emscripten bug: getentropy(buffer, 1) returns the single
298+
// byte of entropy as the return code. Fixed upstream by
299+
// emscripten-core/emscripten#27122
300+
int __real_getentropy(void*, size_t);
301+
302+
int __wrap_getentropy(void *buffer, size_t len) {
303+
if (len != 1) {
304+
return __real_getentropy(buffer, len);
305+
}
306+
// Length is 1. Workaround is to get two bytes of entropy and write the
307+
// first one into the original target buffer.
308+
uint8_t tmp[2];
309+
int ret = __real_getentropy(tmp, 2);
310+
if (ret == 0) {
311+
*(uint8_t *)buffer = tmp[0];
312+
}
313+
return ret;
314+
}
315+
293316
#include <sys/ioctl.h>
294317

295318
int syscall_ioctl_orig(int fd, int request, void* varargs)

configure

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,6 +2411,10 @@ AS_CASE([$ac_sys_system],
24112411
dnl Avoid bugs in JS fallback string decoding path
24122412
AS_VAR_APPEND([LINKFORSHARED], [" -sTEXTDECODER=2"])
24132413
2414+
dnl Workaround for a bug in Emscipten libc's getentropy. See
2415+
dnl __wrap_getentropy in Python/emscripten_syscalls.c.
2416+
AS_VAR_APPEND([LDFLAGS_NODIST], [" -Wl,--wrap=getentropy"])
2417+
24142418
AS_VAR_IF([enable_wasm_dynamic_linking], [yes], [
24152419
AS_VAR_APPEND([LINKFORSHARED], [" -sMAIN_MODULE"])
24162420
])

0 commit comments

Comments
 (0)