summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorHood Chatham <roberthoodchatham@gmail.com>2022-04-03 20:58:52 (GMT)
committerGitHub <noreply@github.com>2022-04-03 20:58:52 (GMT)
commit087d0fa5b97796560c0d8ceab4f0360fd54baf4f (patch)
tree975274b43e0cc50d11f70ba0c6a8fd344d74d632 /Python
parentbdc497496548e30fa208a8d98c30bf6d1833ac4c (diff)
downloadcpython-087d0fa5b97796560c0d8ceab4f0360fd54baf4f.zip
cpython-087d0fa5b97796560c0d8ceab4f0360fd54baf4f.tar.gz
cpython-087d0fa5b97796560c0d8ceab4f0360fd54baf4f.tar.bz2
bpo-47176: Interrupt handling for wasm32-emscripten builds without pthreads (GH-32209)
Co-authored-by: Christian Heimes <christian@python.org> Co-authored-by: Brett Cannon <brett@python.org>
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c2
-rw-r--r--Python/emscripten_signal.c56
2 files changed, 58 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 43080f8..68d2920 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -21,6 +21,7 @@
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_sysmodule.h" // _PySys_Audit()
#include "pycore_tuple.h" // _PyTuple_ITEMS()
+#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
#include "code.h"
#include "pycore_dict.h"
@@ -1292,6 +1293,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
}
#define CHECK_EVAL_BREAKER() \
+ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \
if (_Py_atomic_load_relaxed(eval_breaker)) { \
goto handle_eval_breaker; \
}
diff --git a/Python/emscripten_signal.c b/Python/emscripten_signal.c
new file mode 100644
index 0000000..d617ddf
--- /dev/null
+++ b/Python/emscripten_signal.c
@@ -0,0 +1,56 @@
+// To enable signal handling, the embedder should:
+// 1. set Module.Py_EmscriptenSignalBuffer = some_shared_array_buffer;
+// 2. set the Py_EMSCRIPTEN_SIGNAL_HANDLING flag to 1 as follows:
+// Module.HEAP8[Module._Py_EMSCRIPTEN_SIGNAL_HANDLING] = 1
+//
+// The address &Py_EMSCRIPTEN_SIGNAL_HANDLING is exported as
+// Module._Py_EMSCRIPTEN_SIGNAL_HANDLING.
+#include <emscripten.h>
+#include "Python.h"
+
+EM_JS(int, _Py_CheckEmscriptenSignals_Helper, (void), {
+ if (!Module.Py_EmscriptenSignalBuffer) {
+ return 0;
+ }
+ try {
+ let result = Module.Py_EmscriptenSignalBuffer[0];
+ Module.Py_EmscriptenSignalBuffer[0] = 0;
+ return result;
+ } catch(e) {
+#if !defined(NDEBUG)
+ console.warn("Error occurred while trying to read signal buffer:", e);
+#endif
+ return 0;
+ }
+});
+
+EMSCRIPTEN_KEEPALIVE int Py_EMSCRIPTEN_SIGNAL_HANDLING = 0;
+
+void
+_Py_CheckEmscriptenSignals(void)
+{
+ if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {
+ return;
+ }
+ int signal = _Py_CheckEmscriptenSignals_Helper();
+ if (signal) {
+ PyErr_SetInterruptEx(signal);
+ }
+}
+
+
+#define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50
+static int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;
+
+void
+_Py_CheckEmscriptenSignalsPeriodically(void)
+{
+ if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {
+ return;
+ }
+ emscripten_signal_clock--;
+ if (emscripten_signal_clock == 0) {
+ emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;
+ _Py_CheckEmscriptenSignals();
+ }
+}