Repository navigation
jit.c may be built with an incomplete jit_stencils.h #118943
Description
Bug report
Bug description:
As discussed in https://discuss.python.org/t/pep-744-jit-compilation/50756/42 and further with @brandtbucher, I've tried to change the Fedora's Python 3.13 package to utilize --enable-experimental-jit=yes-off.
As a starting point, I took the 3.13.0b1-1 package from:
https://src.fedoraproject.org/rpms/python3.13/blob/1c24374362/f/python3.13.spec
And I changed:
diff --git a/python3.13.spec b/python3.13.spec
index 4bfe050..68b357d 100644
--- a/python3.13.spec
+++ b/python3.13.spec
@@ -304,6 +304,9 @@ BuildRequires: tcl-devel
BuildRequires: tk-devel
BuildRequires: tzdata
+BuildRequires: clang >= 18
+BuildRequires: llvm >= 18
+
%if %{with valgrind}
BuildRequires: valgrind-devel
%endif
@@ -920,12 +923,12 @@ BuildPython() {
# option produces too many warnings when compiling at the O0 optimization level.
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1818857
BuildPython debug \
- "--without-ensurepip --with-pydebug" \
+ "--without-ensurepip --with-pydebug --enable-experimental-jit=yes-off" \
"%{optflags_debug}"
%endif # with debug_build
BuildPython optimized \
- "--without-ensurepip %{optimizations_flag}" \
+ "--without-ensurepip --enable-experimental-jit=yes-off %{optimizations_flag}" \
"%{optflags_optimized}"
%if %{with freethreading_build} && %{with debug_build}That means I added --enable-experimental-jit=yes-off to the debug and optimized non-free-threaded builds and some extra build dependencies.
Running the build in Fedora Rawhide (41) chroot resulted in this error during the debug build (which happens first):
python3.13 /builddir/build/BUILD/Python-3.13.0b1/Tools/jit/build.py x86_64-redhat-linux-gnu --debug
==============================================================
JIT support for x86_64-redhat-linux-gnu is still experimental!
Please report any issues you encounter.
==============================================================
python3.13 /builddir/build/BUILD/Python-3.13.0b1/Tools/jit/build.py x86_64-redhat-linux-gnu --debug
==============================================================
JIT support for x86_64-redhat-linux-gnu is still experimental!
Please report any issues you encounter.
==============================================================
gcc -c -fno-strict-overflow -Wsign-compare -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -DDYNAMIC_ANNOTATIONS_ENABLED=1 -fcf-protection -fexceptions -fcf-protection -fexceptions -fcf-protection -fexceptions -O0 -Wno-cpp -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -D_GNU_SOURCE -fPIC -fwrapv -D_Py_TIER2=3 -D_Py_JIT -flto -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -g -std=c11 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Wno-complain-wrong-lang -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -mtls-dialect=gnu2 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -D_GNU_SOURCE -fPIC -fwrapv -O0 -Wno-cpp -I/builddir/build/BUILD/Python-3.13.0b1/Include/internal -I/builddir/build/BUILD/Python-3.13.0b1/Include/internal/mimalloc -IObjects -IInclude -IPython -I. -I/builddir/build/BUILD/Python-3.13.0b1/Include -fPIC -DPy_BUILD_CORE -o Python/jit.o /builddir/build/BUILD/Python-3.13.0b1/Python/jit.c
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c: In function ‘emit__MATCH_MAPPING’:
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:395:1: error: expected expression before ‘int’
395 | int
| ^~~
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:479:1: error: expected declaration or statement at end of input
479 | }
| ^
In file included from /builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:392:
./jit_stencils.h:30254:25: warning: unused variable ‘data_body’ [-Wunused-variable]
30254 | const unsigned char data_body[24] = {
| ^~~~~~~~~
./jit_stencils.h:30241:25: warning: unused variable ‘code_body’ [-Wunused-variable]
30241 | const unsigned char code_body[53] = {
| ^~~~~~~~~
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c: At top level:
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:87:1: warning: ‘mark_executable’ defined but not used [-Wunused-function]
87 | mark_executable(unsigned char *memory, size_t size)
| ^~~~~~~~~~~~~~~
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:70:1: warning: ‘jit_free’ defined but not used [-Wunused-function]
70 | jit_free(unsigned char *memory, size_t size)
| ^~~~~~~~
/builddir/build/BUILD/Python-3.13.0b1/Python/jit.c:49:1: warning: ‘jit_alloc’ defined but not used [-Wunused-function]
49 | jit_alloc(size_t size)
| ^~~~~~~~~
make: *** [Makefile:3018: Python/jit.o] Error 1
make: *** Waiting for unfinished jobs....
Full logs:
@brandtbucher suggested that "perhaps several builds are happening at once for some reason. If so, they could be stepping on each other and maybe truncating the generated file."
Anyway, here is the generated jit_stencils.h file as it was present after the failure.
CPython versions tested on:
3.13
Operating systems tested on:
Linux
Linked PRs
- GH-118943: Fix a race condition when generating
jit_stencils.h#118957 - [3.13] GH-118943: Fix a race condition when generating jit_stencils.h (GH-118957) #119101
- GH-118943: Fix another race condition when generating jit_stencils.h #120690
- gh-118943: Remove 'regen-jit' from the 'regen-all' make target #122602
- [3.13] GH-118943: Handle races when moving jit_stencils.h (GH-120690) #122709
- [3.13] GH-118943: Remove regen-jit from the regen-all make target (GH-122602) #122840
Activity
hroncok commentedon May 11, 2024
I've test-built the package in the Fedora build system.
https://koji.fedoraproject.org/koji/taskinfo?taskID=117554410 (this will eventually be garbage collected)
Some architectures succeeded and some failed with:
I suppose this is expected.
But the problem reported here did not happen. Perhaps it only happens sometimes... ? I will trigger a couple of x86_64 builds to see if I can reproduce this again.
brandtbucher commentedon May 11, 2024
Theory:
I noticed we currently don't do an atomic rename of
jit_stencils.h, and just write it incrementally instead. I think ifmakesees the partially-written file, it'll start compilingjit.cand the bottom of the included file will be missing?hroncok commentedon May 11, 2024
Out of 10 builds, I did not reproduce this again.
brandtbucher commentedon May 11, 2024
Yeah, we're not attempting to support anything that isn't at least in PEP 11 right now.
Well, yeah, these ones are intentionally failing early since we won't even attempt to build the JIT. So no
jit_stencils.his generated, andjit.cis never compiled, and the build stops there.By the way, it appears my hunch is correct. With careful use of parallel build and manually inserted
time.sleepcalls, I've been able to coax out similar errors from the compiler (from including a half-generatedjit_stencils.h). It happens ifjit.cis scheduled to build after the file has been opened for writing but before it's finished writing.So writing to a different file
jit_stencils.h.newand doing a rename after is probably the fix here.[-]JIT compiler in Fedora python3.13 package: Python/jit.c:395:1: error: expected expression before ‘int’[/-][+]`jit.c` may be built with an incomplete `jit_stencils.h`[/+]GH-118943: Fix a race condition when generating jit_stencils.h (GH-11…
pythonGH-118943: Fix a race condition when generating jit_stencils.h (p…
[3.13] GH-118943: Fix a race condition when generating jit_stencils.h (…
hroncok commentedon Jun 18, 2024
FWIW I just seen:
This is slightly better than before, but still not entirely OK. I guess when this happens, it means another process created and moved the new file at the same time.
Perhaps the file needs to have a uniq path, and/or be in tmp?
hroncok commentedon Jun 18, 2024
I got it on x86_64 as well, twice in a row. Both builders had 48 CPUs, so the
makecall was heavily parallelized.Should I open a new issue?
6 remaining items
pythongh-118943: Remove 'regen-jit' from the 'regen-all' target
pythongh-118943: Remove 'regen-jit' from the 'regen-all' make target
GH-118943: Handle races when moving jit_stencils.h (GH-120690)
pythonGH-118943: Handle races when moving jit_stencils.h (pythonGH-12…
00429: pythonGH-118943: Fix another race condition when generating ji…
pythonGH-118943: Handle races when moving jit_stencils.h (pythonGH-12…
GH-118943: Remove regen-jit from the regen-all make target (GH-122602)
pythonGH-118943: Remove regen-jit from the regen-all make target (pyt…
[3.13] GH-118943: Handle races when moving jit_stencils.h (GH-122709)
[3.13] GH-118943: Remove regen-jit from the regen-all make target (GH…
brandtbucher commentedon Aug 8, 2024
Thanks again, @hroncok!
pythonGH-118943: Handle races when moving jit_stencils.h (pythonGH-12…
pythonGH-118943: Remove regen-jit from the regen-all make target (pyt…