diff --git a/android/build.sh b/android/build.sh index b1870f7..981794e 100755 --- a/android/build.sh +++ b/android/build.sh @@ -57,6 +57,12 @@ if [ $version_int -eq 312 ]; then # Android tooling; this 3.12-only patch matches that behavior at link time. patches+=" soname_linktime bldlibrary grp" fi +if [ $version_int -ge 313 ]; then + # mimalloc (bundled since 3.13) issues a bare SYS_open at load on x86_64, + # which Android seccomp kills (SIGSYS) at dlopen of libpython. Switch it to + # SYS_openat. See patches/mimalloc_seccomp_openat.patch. + patches+=" mimalloc_seccomp_openat" +fi for name in $patches; do patch_file="$script_dir/patches/$name.patch" echo "$patch_file" diff --git a/android/patches/mimalloc_seccomp_openat.patch b/android/patches/mimalloc_seccomp_openat.patch new file mode 100644 index 0000000..b427cdf --- /dev/null +++ b/android/patches/mimalloc_seccomp_openat.patch @@ -0,0 +1,22 @@ +mimalloc: use SYS_openat instead of SYS_open (Android seccomp). + +CPython bundles mimalloc since 3.13. On Android, mimalloc's load-time constructor +(mi_process_load -> unix_detect_overcommit, Objects/mimalloc/init.c) reads +/proc/sys/vm/overcommit_memory through mi_prim_open. On platforms where SYS_open +is defined (x86_64) mi_prim_open issues the bare open(2) syscall directly (to +avoid recursion while mimalloc is still initializing). Android's bionic seccomp +policy forbids open(2) -- only openat(2) is permitted -- so the kernel raises +SIGSYS (SYS_SECCOMP) and the process is killed at dlopen() of libpython, before +the interpreter starts. 3.12 has no mimalloc; arm64 is unaffected (it has no +SYS_open, so mimalloc falls back to libc open(), which bionic routes through +openat). SYS_openat(AT_FDCWD, ...) is semantically identical and allowed. + +--- a/Objects/mimalloc/prim/unix/prim.c ++++ b/Objects/mimalloc/prim/unix/prim.c +@@ -67,5 +67,5 @@ + static int mi_prim_open(const char* fpath, int open_flags) { +- return syscall(SYS_open,fpath,open_flags,0); ++ return syscall(SYS_openat,AT_FDCWD,fpath,open_flags,0); + } + static ssize_t mi_prim_read(int fd, void* buf, size_t bufsize) { + return syscall(SYS_read,fd,buf,bufsize); diff --git a/android/python-android-dart.exclude b/android/python-android-dart.exclude index cee3d2d..2d95dbd 100644 --- a/android/python-android-dart.exclude +++ b/android/python-android-dart.exclude @@ -20,8 +20,8 @@ lib/python*/tkinter lib/python*/turtle* lib/python*/wsgiref # Interactive-REPL / dev-only modules + easter eggs / frozen demos (never imported when -# running a script in embedded mode). -lib/python*/_pyrepl +# running a script in embedded mode). _pyrepl is intentionally NOT pruned: CPython 3.14's +# pdb imports it at module load, so dropping it breaks pdb / pytest / anything that imports it. lib/python*/rlcompleter* lib/python*/tabnanny* lib/python*/antigravity* diff --git a/darwin/python-darwin-stdlib.exclude b/darwin/python-darwin-stdlib.exclude index 64725c9..03fb233 100644 --- a/darwin/python-darwin-stdlib.exclude +++ b/darwin/python-darwin-stdlib.exclude @@ -19,8 +19,9 @@ tkinter turtle* wsgiref # Interactive-REPL / dev-only modules — never imported when running a script (embedded -# mode); plus easter eggs and frozen demo modules. -_pyrepl +# mode); plus easter eggs and frozen demo modules. _pyrepl is intentionally NOT pruned: +# CPython 3.14's pdb imports it at module load, so dropping it breaks pdb / pytest / +# anything that imports it on-device. rlcompleter* tabnanny* antigravity*