Commit 18da211e authored by Michael Droettboom's avatar Michael Droettboom Committed by GitHub

Merge pull request #87 from mdboom/call-stack-size-exceeded

Decrease Python call stack size so it doesn't exceed JS call stack
parents c61659db 9d743632
......@@ -268,9 +268,9 @@ JsProxy_GetBuffer(PyObject* o, Py_buffer* view, int flags)
Py_ssize_t byteLength = hiwire_get_byteLength(self->js);
void *ptr;
void* ptr;
if (hiwire_is_on_wasm_heap(self->js)) {
ptr = (void *)hiwire_get_byteOffset(self->js);
ptr = (void*)hiwire_get_byteOffset(self->js);
} else {
if (self->bytes == NULL) {
self->bytes = PyBytes_FromStringAndSize(NULL, byteLength);
......@@ -347,8 +347,9 @@ JsProxy_GetBuffer(PyObject* o, Py_buffer* view, int flags)
}
static PyObject*
JsProxy_HasBytes(PyObject *o) {
JsProxy* self = (JsProxy *)o;
JsProxy_HasBytes(PyObject* o)
{
JsProxy* self = (JsProxy*)o;
if (self->bytes == NULL) {
Py_RETURN_FALSE;
......
......@@ -69,6 +69,32 @@ var languagePluginLoader = new Promise((resolve, reject) => {
return promise;
};
function fixRecursionLimit(pyodide) {
// The Javascript/Wasm call stack may be too small to handle the default
// Python call stack limit of 1000 frames. This is generally the case on
// Chrom(ium), but not on Firefox. Here, we determine the Javascript call
// stack depth available, and then divide by 50 (determined heuristically)
// to set the maximum Python call stack depth.
let depth = 0;
function recurse() {
depth += 1;
recurse();
}
try {
recurse();
} catch (err) {
;
}
let recursionLimit = depth / 50;
if (recursionLimit > 1000) {
recursionLimit = 1000;
}
pyodide.runPython(
`import sys; sys.setrecursionlimit(int(${recursionLimit}))`);
};
////////////////////////////////////////////////////////////
// Loading Pyodide
let wasmURL = `${baseURL}pyodide.asm.wasm`;
......@@ -98,6 +124,7 @@ var languagePluginLoader = new Promise((resolve, reject) => {
.then((response) => response.json())
.then((json) => {
window.pyodide.packages = json;
fixRecursionLimit(pyodide);
resolve();
});
};
......
......@@ -9,19 +9,19 @@
extern PyObject* globals;
PyObject *eval_code;
PyObject* eval_code;
int
_runPython(char* code)
{
PyObject *py_code;
PyObject* py_code;
py_code = PyUnicode_FromString(code);
if (py_code == NULL) {
return pythonexc2js();
}
PyObject *ret = PyObject_CallFunctionObjArgs(
eval_code, py_code, globals, NULL);
PyObject* ret =
PyObject_CallFunctionObjArgs(eval_code, py_code, globals, NULL);
if (ret == NULL) {
return pythonexc2js();
......@@ -46,13 +46,15 @@ EM_JS(int, runpython_init_js, (), {
return 0;
});
int runpython_init_py() {
PyObject *m = PyImport_ImportModule("pyodide");
int
runpython_init_py()
{
PyObject* m = PyImport_ImportModule("pyodide");
if (m == NULL) {
return 1;
}
PyObject *d = PyModule_GetDict(m);
PyObject* d = PyModule_GetDict(m);
if (d == NULL) {
return 1;
}
......
......@@ -53,7 +53,11 @@ class SeleniumWrapper:
'return pyodide.runPython({!r})'.format(code))
def run_js(self, code):
return self.driver.execute_script(code)
catch = f"""
Error.stackTraceLimit = Infinity;
try {{ {code} }}
catch (error) {{ console.log(error.stack); throw error; }}"""
return self.driver.execute_script(catch)
def load_package(self, packages):
self.run_js(
......
import os
import pathlib
import time
......@@ -281,13 +280,13 @@ def test_run_core_python_test(python_test, selenium):
"from test.libregrtest import main\n"
"main(['{}'], verbose=True, verbose3=True)".format(python_test))
except selenium.JavascriptException as e:
assert str(e).strip().endswith('SystemExit: 0')
assert 'SystemExit: 0' in str(e)
def pytest_generate_tests(metafunc):
if 'python_test' in metafunc.fixturenames:
test_modules = []
if 'CIRCLECI' not in os.environ:
if True:
with open(
str(pathlib.Path(__file__).parents[0] /
"python_tests.txt")) as fp:
......@@ -299,3 +298,15 @@ def pytest_generate_tests(metafunc):
if len(parts) == 1:
test_modules.append(parts[0])
metafunc.parametrize("python_test", test_modules)
def test_recursive_repr(selenium):
assert not selenium.run(
"d = {}\n"
"d[42] = d.values()\n"
"result = True\n"
"try:\n"
" repr(d)\n"
"except RecursionError:\n"
" result = False\n"
"result")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment