This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author roudkerk
Recipients roudkerk
Date 2007-12-21.18:53:45
SpamBayes Score 0.00043295504
Marked as misclassified No
Message-id <1198263226.4.0.968502752614.issue1683@psf.upfronthosting.co.za>
In-reply-to
Content
I got a report that one of the tests for processing
(http://cheeseshop.python.org/pypi/processing) was failing with

    Fatal Python error: Invalid thread state for this thread

when run with a debug interpreter.  This appears to be caused by the
interaction between os.fork() and threads.  The following attached
program reliably reproduces the problem for me on Ubuntu edgy for x86.

All that happens is that the parent process starts a subthread then
forks, and then the child process starts a subthread.

With the normal interpreter I get

    started thread -1211028576 in process 18683
    I am thread -1211028576 in process 18683
    started thread -1211028576 in process 18685
    I am thread -1211028576 in process 18685

as expected, but with the debug interpreter I get

    started thread -1210782816 in process 18687
    I am thread -1210782816 in process 18687
    started thread -1210782816 in process 18689
    Fatal Python error: Invalid thread state for this thread
    [5817 refs]

Notice that the child process is reusing a thread id that was 
being used by the parent process at the time of the fork.

The code raising the error seems to be in pystate.c:

    PyThreadState *
    PyThreadState_Swap(PyThreadState *new)
    {
            PyThreadState *old = _PyThreadState_Current;

            _PyThreadState_Current = new;
            /* It should not be possible for more than one thread state
               to be used for a thread.  Check this the best we can in
debug 
               builds.
            */
    #if defined(Py_DEBUG) && defined(WITH_THREAD)
            if (new) {
                    PyThreadState *check = PyGILState_GetThisThreadState();
                    if (check && check != new)
                            Py_FatalError("Invalid thread state for this
thread");
            }
    #endif
            return old;
    }

It looks as though PyGILState_GetThisThreadState() is returning the
thread state of the thread from the parent process which has the same
id as the current thread.  Therefore the check fails.

I think the thread local storage implementation in thread.c should
provide a function _PyThread_ReInitTLS() which PyOS_AfterFork() can
call.  I think _PyThread_ReInitTLS() just needs to remove and free
each "struct key" in the linked list which does not match the id of
the calling thread.
Files
File name Uploaded
dbg2.py roudkerk, 2007-12-21.18:53:45
History
Date User Action Args
2007-12-21 18:53:46roudkerksetspambayes_score: 0.000432955 -> 0.00043295504
recipients: + roudkerk
2007-12-21 18:53:46roudkerksetspambayes_score: 0.000432955 -> 0.000432955
messageid: <1198263226.4.0.968502752614.issue1683@psf.upfronthosting.co.za>
2007-12-21 18:53:46roudkerklinkissue1683 messages
2007-12-21 18:53:45roudkerkcreate