8000 gh-90473: Decrease recursion limit and skip tests on WASI (GH-92803) · varunsh-coder/cpython@137fd3d · GitHub
[go: up one dir, main page]

Skip to content

Commit 137fd3d

Browse files
authored
pythongh-90473: Decrease recursion limit and skip tests on WASI (pythonGH-92803)
1 parent e48ac9c commit 137fd3d

File tree

20 files changed

+109
-14
lines changed

20 files changed

+109
-14
lines changed

Include/internal/pycore_ceval.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ extern "C" {
1212
struct pyruntimestate;
1313
struct _ceval_runtime_state;
1414

15+
/* WASI has limited call stack. wasmtime 0.36 can handle sufficient amount of
16+
C stack frames for little more than 750 recursions. */
1517
#ifndef Py_DEFAULT_RECURSION_LIMIT
16-
# define Py_DEFAULT_RECURSION_LIMIT 1000
18+
# ifdef __wasi__
19+
# define Py_DEFAULT_RECURSION_LIMIT 750
20+
# else
21+
# define Py_DEFAULT_RECURSION_LIMIT 1000
22+
# endif
1723
#endif
1824

1925
#include "pycore_interp.h" // PyInterpreterState.eval_frame

Lib/platform.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ def libc_ver(executable=None, lib='', version='', chunksize=16384):
186186

187187
executable = sys.executable
188188

189+
< 6D40 span class=pl-k>if not executable:
190+
# sys.executable is not set.
191+
return lib, version
192+
189193
V = _comparable_version
190194
# We use os.path.realpath()
191195
# here to work around problems with Cygwin not being

Lib/test/pythoninfo.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,14 @@ def format_attr(attr, value):
545545
def collect_socket(info_add):
546546
import socket
547547

548-
hostname = socket.gethostname()
549-
info_add('socket.hostname', hostname)
548+
try:
549+
hostname = socket.gethostname()
550+
except OSError:
551+
# WASI SDK 15.0 does not have gethostname(2).
552+
if sys.platform != "wasi":
553+
raise
554+
else:
555+
info_add('socket.hostname', hostname)
550556

551557

552558
def collect_sqlite(info_add):

Lib/test/support/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ def get_original_stdout():
199199
def _force_run(path, func, *args):
200200
try:
201201
return func(*args)
202+
except FileNotFoundError as err:
203+
# chmod() won't fix a missing file.
204+
if verbose >= 2:
205+
print('%s: %s' % (err.__class__.__name__, err))
206+
raise
202207
except OSError as err:
203208
if verbose >= 2:
204209
print('%s: %s' % (err.__class__.__name__, err))

Lib/test/test_compile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ def __getitem__(self, key):
109109
self.assertEqual(d['z'], 12)
110110

111111
def test_extended_arg(self):
112-
longexpr = 'x = x or ' + '-x' * 2500
112+
# default: 1000 * 2.5 = 2500 repetitions
113+
repeat = int(sys.getrecursionlimit() * 2.5)
114+
longexpr = 'x = x or ' + '-x' * repeat
113115
g = {}
114116
code = '''
115117
def f(x):

Lib/test/test_fileio.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
from weakref import proxy
1010
from functools import wraps
1111

12-
from test.support import cpython_only, swap_attr, gc_collect, is_emscripten
12+
from test.support import (
13+
cpython_only, swap_attr, gc_collect, is_emscripten, is_wasi
14+
)
1315
from test.support.os_helper import (TESTFN, TESTFN_UNICODE, make_bad_fd)
1416
from test.support.warnings_helper import check_warnings
1517
from collections import UserList
@@ -65,6 +67,7 @@ def testAttributes(self):
6567
self.assertRaises((AttributeError, TypeError),
6668
setattr, f, attr, 'oops')
6769

70+
@unittest.skipIf(is_wasi, "WASI does not expose st_blksize.")
6871
def testBlksize(self):
6972
# test private _blksize attribute
7073
blksize = io.DEFAULT_BUFFER_SIZE

Lib/test/test_largefile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ def test_seekable(self):
156156
def skip_no_disk_space(path, required):
157157
def decorator(fun):
158158
def wrapper(*args, **kwargs):
159+
if not hasattr(shutil, "disk_usage"):
160+
raise unittest.SkipTest("requires shutil.disk_usage")
159161
if shutil.disk_usage(os.path.realpath(path)).free < required:
160162
hsize = int(required / 1024 / 1024)
161163
raise unittest.SkipTest(

Lib/test/test_logging.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5280,6 +5280,7 @@ def test_emit_after_closing_in_write_mode(self):
52805280
self.assertEqual(fp.read().strip(), '1')
52815281

52825282
class RotatingFileHandlerTest(BaseFileTest):
5283+
@unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.")
52835284
def test_should_not_rollover(self):
52845285
# If maxbytes is zero rollover never occurs
52855286
rh = logging.handlers.RotatingFileHandler(
@@ -5387,6 +5388,7 @@ def rotator(source, dest):
53875388
rh.close()
53885389

53895390
class TimedRotatingFileHandlerTest(BaseFileTest):
5391+
@unittest.skipIf(support.is_wasi, "WASI does not have /dev/null.")
53905392
def test_should_not_rollover(self):
53915393
# See bpo-45401. Should only ever rollover regular files
53925394
fh = logging.handlers.TimedRotatingFileHandler(

Lib/test/test_os.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import fractions
1212
import itertools
1313
import locale
14-
import mmap
1514
import os
1615
import pickle
1716
import select
@@ -59,6 +58,10 @@
5958
except ImportError:
6059
INT_MAX = PY_SSIZE_T_MAX = sys.maxsize
6160

61+
try:
62+
import mmap
63+
except ImportError:
64+
mmap = None
6265

6366
from test.support.script_helper import assert_python_ok
6467
from test.support import unix_shell
@@ -2167,7 +2170,8 @@ def test_fchown(self):
21672170

21682171
@unittest.skipUnless(hasattr(os, 'fpathconf'), 'test needs os.fpathconf()')
21692172
@unittest.skipIf(
2170-
support.is_emscripten, "musl libc issue on Emscripten, bpo-46390"
2173+
support.is_emscripten or support.is_wasi,
2174+
"musl libc issue on Emscripten/WASI, bpo-46390"
21712175
)
21722176
def test_fpathconf(self):
21732177
self.check(os.pathconf, "PC_NAME_MAX")
@@ -2460,6 +2464,7 @@ def test_kill_int(self):
24602464
# os.kill on Windows can take an int which gets set as the exit code
24612465
self._kill(100)
24622466

2467+
@unittest.skipIf(mmap is None, "requires mmap")
24632468
def _kill_with_event(self, event, name):
24642469
tagname = "test_os_%s" % uuid.uuid1()
24652470
m = mmap.mmap(-1, 1, tagname)

Lib/test/test_signal.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def test_interprocess_signal(self):
107107
script = os.path.join(dirname, 'signalinterproctester.py')
108108
assert_python_ok(script)
109109

110+
@unittest.skipUnless(
111+
hasattr(signal, "valid_signals"),
112+
"requires signal.valid_signals"
113+
)
110114
def test_valid_signals(self):
111115
s = signal.valid_signals()
112116
self.assertIsInstance(s, set)
@@ -212,6 +216,7 @@ def test_invalid_fd(self):
212216
self.assertRaises((ValueError, OSError),
213217
signal.set_wakeup_fd, fd)
214218

219+
@unittest.skipUnless(support.has_socket_support, "needs working sockets.")
215220
def test_invalid_socket(self):
216221
sock = socket.socket()
217222
fd = sock.fileno()
@@ -241,6 +246,7 @@ def test_set_wakeup_fd_result(self):
241246
self.assertEqual(signal.set_wakeup_fd(-1), -1)
242247

243248
@unittest.skipIf(support.is_emscripten, "Emscripten cannot fstat pipes.")
249+
@unittest.skipUnless(support.has_socket_support, "needs working sockets.")
244250
def test_set_wakeup_fd_socket_result(self):
245251
sock1 = socket.socket()
246252
self.addCleanup(sock1.close)

Lib/test/test_tomllib/test_misc.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import datetime
77
from decimal import Decimal as D
88
from pathlib import Path
9+
import sys
910
import tempfile
1011
import unittest
1112

@@ -91,11 +92,13 @@ def test_deepcopy(self):
9192
self.assertEqual(obj_copy, expected_obj)
9293

9394
def test_inline_array_recursion_limit(self):
94-
nest_count = 470
95+
# 470 with default recursion limit
96+
nest_count = int(sys.getrecursionlimit() * 0.47)
9597
recursive_array_toml = "arr = " + nest_count * "[" + nest_count * "]"
9698
tomllib.loads(recursive_array_toml)
9799

98100
def test_inline_table_recursion_limit(self):
99-
nest_count = 310
101+
# 310 with default recursion limit
102+
nest_count = int(sys.getrecursionlimit() * 0.31)
100103
recursive_table_toml = nest_count * "key = {" + nest_count * "}"
101104
tomllib.loads( 10000 recursive_table_toml)

Lib/test/test_zipimport.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ def testEmptyFile(self):
804804
os_helper.create_empty_file(TESTMOD)
805805
self.assertZipFailure(TESTMOD)
806806

807+
@unittest.skipIf(support.is_wasi, "mode 000 not supported.")
807808
def testFileUnreadable(self):
808809
os_helper.unlink(TESTMOD)
809810
fd = os.open(TESTMOD, os.O_CREAT, 000)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Decrease default recursion limit on WASI to address limited call stack size.

Modules/timemodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ _PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
14811481

14821482
#elif defined(HAVE_CLOCK_GETTIME) && \
14831483
defined(CLOCK_PROCESS_CPUTIME_ID) && \
1484-
!defined(__EMSCRIPTEN__)
1484+
!defined(__EMSCRIPTEN__) && !defined(__wasi__)
14851485
#define HAVE_THREAD_TIME
14861486

14871487
#if defined(__APPLE__) && defined(__has_attribute) && __has_attribute(availability)

Parser/parser.c

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Tools/peg_generator/pegen/c_generator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@
3737
# define D(x)
3838
#endif
3939
40-
# define MAXSTACK 6000
40+
#ifdef __wasi__
41+
# define MAXSTACK 4000
42+
#else
43+
# define MAXSTACK 6000
44+
#endif
4145
4246
"""
4347

Tools/wasm/README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,27 @@ AddType application/wasm wasm
220220

221221
# WASI (wasm32-wasi)
222222

223-
WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) and
224-
currently [wasix](https://github.com/singlestore-labs/wasix) for POSIX
223+
WASI builds require [WASI SDK](https://github.com/WebAssembly/wasi-sdk) 15.0+
224+
and currently [wasix](https://github.com/singlestore-labs/wasix) for POSIX
225225
compatibility stubs.
226226

227+
## WASI limitations and issues (WASI SDK 15.0)
228+
229+
A lot of Emscripten limitations also apply to WASI. Noticable restrictions
230+
are:
231+
232+
- Call stack size is limited. Default recursion limit and parser stack size
233+
are smaller than in regular Python builds.
234+
- ``socket(2)`` cannot create new socket file descriptors. WASI programs can
235+
call read/write/accept on a file descriptor that is passed into the process.
236+
- ``socket.gethostname()`` and host name resolution APIs like
237+
``socket.gethostbyname()`` are not implemented and always fail.
238+
- ``chmod(2)`` is not available. It's not possible to modify file permissions,
239+
yet. A future version of WASI may provide a limited ``set_permissions`` API.
240+
- File locking (``fcntl``) is not available.
241+
- ``os.pipe()``, ``os.mkfifo()``, and ``os.mknod()`` are not supported.
242+
243+
227244
# Detect WebAssembly builds
228245

229246
## Python code

Tools/wasm/config.site-wasm32-wasi

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,24 @@ ac_cv_header_sys_resource_h=no
1717

1818
# undefined symbols / unsupported features
1919
ac_cv_func_eventfd=no
20+
21+
# WASI SDK 15.0 has no pipe syscall.
22+
ac_cv_func_pipe=no
23+
24+
# WASI SDK 15.0 cannot create fifos and special files.
25+
ac_cv_func_mkfifo=no
26+
ac_cv_func_mkfifoat=no
27+
ac_cv_func_mknod=no
28+
ac_cv_func_mknodat=no
29+
30+
# fdopendir() fails on SDK 15.0,
31+
# OSError: [Errno 28] Invalid argument: '.'
32+
ac_cv_func_fdopendir=no
33+
34+
# WASIX stubs we don't want to use.
35+
ac_cv_func_kill=no
36+
37+
# WASI sockets are limited to operations on given socket fd and inet sockets.
38+
# Disable AF_UNIX and AF_PACKET support, see socketmodule.h.
39+
ac_cv_header_sys_un_h=no
40+
ac_cv_header_netpacket_packet_h=no

configure

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

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6690,8 +6690,10 @@ AS_CASE([$ac_sys_system],
66906690
],
66916691
[Emscripten/node*], [],
66926692
[WASI/*], [
6693+
dnl WASI SDK 15.0 does not support file locking.
66936694
PY_STDLIB_MOD_SET_NA(
66946695
[_ctypes_test],
6696+
[fcntl],
66956697
)
66966698
]
66976699
)

0 commit comments

Comments
 (0)
0