Skip to content

test_threading.test_4_daemon_threads() crash randomly#110052

@vstinner

Description

@vstinner

On Linux, when I stress test test_threading.test_4_daemon_threads(), it does crash randomly:

./python -m test test_threading -m test_4_daemon_threads -j50 -F --fail-env-changed 

gdb traceback:

Program terminated with signal SIGSEGV, Segmentation fault. #0 0x00000000006e02f4 in PyInterpreterState_ThreadHead (interp=0xdddddddddddddddd) at Python/pystate.c:1961 warning: Source file is more recent than executable. 1961 return interp->threads.head; [Current thread is 1 (Thread 0x7fcbb8ff96c0 (LWP 510515))] Missing separate debuginfos, use: dnf debuginfo-install bzip2-libs-1.0.8-13.fc38.x86_64 glibc-2.37-5.fc38.x86_64 libffi-3.4.4-2.fc38.x86_64 libgcc-13.2.1-1.fc38.x86_64 openssl-libs-3.0.9-2.fc38.x86_64 xz-libs-5.4.1-1.fc38.x86_64 zlib-1.2.13-3.fc38.x86_64 (gdb) where #0 0x00000000006e02f4 in PyInterpreterState_ThreadHead (interp=0xdddddddddddddddd) at Python/pystate.c:1961 #1 0x0000000000703090 in _Py_DumpTracebackThreads (fd=2, interp=0xdddddddddddddddd, current_tstate=0x24a34e0) at Python/traceback.c:1331 #2 0x000000000071bcef in faulthandler_dump_traceback (fd=2, all_threads=1, interp=0xa53688 <_PyRuntime+92712>) at ./Modules/faulthandler.c:195 #3 0x000000000071bfed in faulthandler_fatal_error (signum=11) at ./Modules/faulthandler.c:313 #4 <signal handler called> #5 0x000000000069f808 in take_gil (tstate=0x24a34e0) at Python/ceval_gil.c:360 #6 0x00000000006a03ab in PyEval_RestoreThread (tstate=0x24a34e0) at Python/ceval_gil.c:714 #7 0x000000000074dd93 in portable_lseek (self=0x7fcc186c3590, posobj=0x0, whence=1, suppress_pipe_error=false) at ./Modules/_io/fileio.c:934 #8 0x000000000074de88 in _io_FileIO_tell_impl (self=0x7fcc186c3590) at ./Modules/_io/fileio.c:997 #9 0x000000000074ea4c in _io_FileIO_tell (self=0x7fcc186c3590, _unused_ignored=0x0) at ./Modules/_io/clinic/fileio.c.h:460 (...) 

gdb debug:

 (gdb) frame 5 #5 0x000000000069f808 in take_gil (tstate=0x24a34e0) at Python/ceval_gil.c:360 360 struct _gil_runtime_state *gil = ceval->gil; (gdb) l 355 } 356 357 assert(_PyThreadState_CheckConsistency(tstate)); 358 PyInterpreterState *interp = tstate->interp; 359 struct _ceval_state *ceval = &interp->ceval; 360 struct _gil_runtime_state *gil = ceval->gil; 361 362 /* Check that _PyEval_InitThreads() was called to create the lock */ 363 assert(gil_created(gil)); 364 (gdb) p /x ceval $1 = 0xdddddddddddddddd (gdb) p /x tstate->interp $2 = 0xdddddddddddddddd (gdb) p /x tstate $5 = 0x24a34e0 (gdb) p /x _PyRuntime._finalizing._value $3 = 0xab8fa8 (gdb) p /x _PyRuntime._finalizing_id $4 = 0x7fcc49fce740 

I don't understand why the test didn't exit: _PyThreadState_MustExit() should return, no?

I don't understand why assert(_PyThreadState_CheckConsistency(tstate)); didn't fail.

Maybe Py_Finalize() was called between the pre-check:

if (_PyThreadState_MustExit(tstate)){/* bpo-39877: If Py_Finalize() has been called and tstate is not the thread which called Py_Finalize(), exit immediately the thread. This code path can be reached by a daemon thread after Py_Finalize() completes. In this case, tstate is a dangling pointer: points to PyThreadState freed memory. */PyThread_exit_thread()} assert(_PyThreadState_CheckConsistency(tstate));

and the code:

PyInterpreterState*interp=tstate->interp; struct_ceval_state*ceval=&interp->ceval; struct_gil_runtime_state*gil=ceval->gil;

Linked PRs

Metadata

Metadata

Labels

testsTests in the Lib/test dir

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions