Skip to content

test_threading.test_4_daemon_threads() crash randomly #110052

Closed
@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