8000 bpo-47176: Interrupt handling for wasm32-emscripten builds without pt… · python/cpython@087d0fa · GitHub
[go: up one dir, main page]

Skip to content

Commit 087d0fa

Browse files
hoodmanetiranbrettcannon
authored
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>
1 parent bdc4974 commit 087d0fa

File tree

8 files changed

+124
-1
lines changed

8 files changed

+124
-1
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef Py_EMSCRIPTEN_SIGNAL_H
2+
#define Py_EMSCRIPTEN_SIGNAL_H
3+
4+
#if defined(__EMSCRIPTEN__)
5+
6+
void
7+
_Py_CheckEmscriptenSignals(void);
8+
9+
void
10+
_Py_CheckEmscriptenSignalsPeriodically(void);
11+
12+
#define _Py_CHECK_EMSCRIPTEN_SIGNALS() _Py_CheckEmscriptenSignals()
13+
14+
#define _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY() _Py_CheckEmscriptenSignalsPeriodically()
15+
16+
extern int Py_EMSCRIPTEN_SIGNAL_HANDLING;
17+
18+
#else
19+
20+
#define _Py_CHECK_EMSCRIPTEN_SIGNALS()
21+
#define _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY()
22+
23+
#endif // defined(__EMSCRIPTEN__)
24+
25+
#endif // ndef Py_EMSCRIPTEN_SIGNAL_H

Makefile.pre.in

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ PYTHON_OBJS= \
429429
Python/$(DYNLOADFILE) \
430430
$(LIBOBJS) \
431431
$(MACHDEP_OBJS) \
432-
$(DTRACE_OBJS)
432+
$(DTRACE_OBJS) \
433+
@PLATFORM_OBJS@
433434

434435

435436
##########################################################################
@@ -1608,6 +1609,7 @@ PYTHON_HEADERS= \
16081609
$(srcdir)/Include/internal/pycore_unicodeobject.h \
16091610
$(srcdir)/Include/internal/pycore_warnings.h \
16101611
$(DTRACE_HEADERS) \
1612+
@PLATFORM_HEADERS@ \
16111613
\
16121614
$(srcdir)/Python/stdlib_module_names.h
16131615

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Emscripten builds cannot handle signals in the usual way due to platform
2+
limitations. Python can now handle signals. To use, set
3+
Module.Py_EmscriptenSignalBuffer to be a single byte SharedArrayBuffer and
4+
set Py_EMSCRIPTEN_SIGNAL_HANDLING to 1. Writing a number into the
5+
SharedArrayBuffer will cause the corresponding signal to be raised into the
6+
Python thread.

Modules/signalmodule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "pycore_pyerrors.h" // _PyErr_SetString()
1414
#include "pycore_pylifecycle.h" // NSIG
1515
#include "pycore_pystate.h" // _PyThreadState_GET()
16+
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
1617

1718
#ifndef MS_WINDOWS
1819
# include "posixmodule.h"
@@ -1797,6 +1798,7 @@ PyErr_CheckSignals(void)
17971798
int
17981799
_PyErr_CheckSignalsTstate(PyThreadState *tstate)
17991800
{
1801+
_Py_CHECK_EMSCRIPTEN_SIGNALS();
18001802
if (!_Py_atomic_load(&is_tripped)) {
18011803
return 0;
18021804
}

Python/ceval.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "pycore_pystate.h" // _PyInterpreterState_GET()
2222
#include "pycore_sysmodule.h" // _PySys_Audit()
2323
#include "pycore_tuple.h" // _PyTuple_ITEMS()
24+
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
2425

2526
#include "code.h"
2627
#include "pycore_dict.h"
@@ -1292,6 +1293,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
12921293
}
12931294

12941295
#define CHECK_EVAL_BREAKER() \
1296+
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \
12951297
if (_Py_atomic_load_relaxed(eval_breaker)) { \
12961298
goto handle_eval_breaker; \
12971299
}

Python/emscripten_signal.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// To enable signal handling, the embedder should:
2+
// 1. set Module.Py_EmscriptenSignalBuffer = some_shared_array_buffer;
3+
// 2. set the Py_EMSCRIPTEN_SIGNAL_HANDLING flag to 1 as follows:
4+
// Module.HEAP8[Module._Py_EMSCRIPTEN_SIGNAL_HANDLING] = 1
5+
//
6+
// The address &Py_EMSCRIPTEN_SIGNAL_HANDLING is exported as
7+
// Module._Py_EMSCRIPTEN_SIGNAL_HANDLING.
8+
#include <emscripten.h>
9+
#include "Python.h"
10+
11+
EM_JS(int, _Py_CheckEmscriptenSignals_Helper, (void), {
12+
if (!Module.Py_EmscriptenSignalBuffer) {
13+
return 0;
14+
}
15+
try {
16+
let result = Module.Py_EmscriptenSignalBuffer[0];
17+
Module.Py_EmscriptenSignalBuffer[0] = 0;
18+
return result;
19+
} catch(e) {
20+
#if !defined(NDEBUG)
21+
console.warn("Error occurred while trying to read signal buffer:", e);
22+
#endif
23+
return 0;
24+
}
25+
});
26+
27+
EMSCRIPTEN_KEEPALIVE int Py_EMSCRIPTEN_SIGNAL_HANDLING = 0;
28+
29+
void
30+
_Py_CheckEmscriptenSignals(void)
31+
{
32+
if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {
33+
return;
34+
}
35+
int signal = _Py_CheckEmscriptenSignals_Helper();
36+
if (signal) {
37+
PyErr_SetInterruptEx(signal);
38+
}
39+
}
40+
41+
42+
#define PY_EMSCRIPTEN_SIGNAL_INTERVAL 50
43+
static int emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;
44+
45+
void
46+
_Py_CheckEmscriptenSignalsPeriodically(void)
47+
{
48+
if (!Py_EMSCRIPTEN_SIGNAL_HANDLING) {
49+
return;
50+
}
51+
emscripten_signal_clock--;
52+
if (emscripten_signal_clock == 0) {
53+
emscripten_signal_clock = PY_EMSCRIPTEN_SIGNAL_INTERVAL;
54+
_Py_CheckEmscriptenSignals();
55+
}
56+
}

configure

Lines changed: 17 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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4187,6 +4187,19 @@ then
41874187
fi
41884188
fi
41894189

4190+
dnl Platform-specific C and header files.
4191+
PLATFORM_HEADERS=
4192+
PLATFORM_OBJS=
4193+
4194+
AS_CASE([$ac_sys_system],
4195+
[Emscripten], [
4196+
AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_signal.o'])
4197+
AS_VAR_APPEND([PLATFORM_HEADERS], [' $(srcdir)/Include/internal/pycore_emscripten_signal.h'])
4198+
],
4199+
)
4200+
AC_SUBST([PLATFORM_HEADERS])
4201+
AC_SUBST([PLATFORM_OBJS])
4202+
41904203
# -I${DLINCLDIR} is added to the compile rule for importdl.o
41914204
AC_SUBST(DLINCLDIR)
41924205
DLINCLDIR=.

0 commit comments

Comments
 (0)
0