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.
Created on 2009年12月19日 12:49 by vstinner, last changed 2022年04月11日 14:56 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| thread_prealloc_pystate-4.patch | vstinner, 2010年01月31日 23:50 | |||
| Messages (20) | |||
|---|---|---|---|
| msg96602 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2009年12月19日 12:49 | |
Using my fuzzer (Fusil) on Python trunk, I got sometimes errors on multiprocessing.Pool(): Fatal Python error: PyEval_AcquireThread: NULL new thread state I'm sorry but I don't have example script to reproduce the bug. I suppose that the error depends on the system load. I have the error on an Intel Core2 Quad Core Q9300 (CPU able to run 4 processes/threads at the time same). How can I get more information on the bug? How can I reproduce it? |
|||
| msg96610 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2009年12月19日 16:26 | |
Enable core dumps (`ulimit -c unlimited`) and re-run your tests. The fatal Python error will leave a core file so that you can find out the context. You can also try a debug build of Python which may give you more information, assuming it can reproduce the bug. (as for how to reproduce the bug, it's your task to find it out :-)) |
|||
| msg96658 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2009年12月20日 01:09 | |
Use a core dump: good idea! haypo> Using my fuzzer (Fusil) on Python trunk, I got sometimes haypo> errors on multiprocessing.Pool(): haypo> haypo> Fatal Python error: PyEval_AcquireThread: NULL new thread state I read the source code of the thread module. This error means that PyThreadState_New() returns NULL which occurs if malloc() failed. I hit this error using my fuzzer because the fuzzer limits the total memory to something around 100 MB using setrlimit(). Said differently: in low memory condition, creating a new thread may exit the whole Python process if a memory allocation fail. -- Sometimes, I get another error, similar to the "NULL new thread state" error: Fatal Python error: Couldn't create autoTLSkey mapping I guess that the reason is the same: memory allocation failed. It should be the malloc() in find_key() (Python/thread.c). |
|||
| msg96760 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2009年12月21日 16:46 | |
We just had this error on one of the buildbots: [...] test_threadsignals sem_wait: Unknown error 512 test_docxmlrpc Fatal Python error: Invalid thread state for this thread Fatal Python error: PyEval_AcquireThread: non-NULL old thread state make: *** [buildbottest] Aborted (see http://www.python.org/dev/buildbot/all/builders/x86%20Ubuntu%20trunk/builds/161/steps/test/logs/stdio ) I don't know it's related. |
|||
| msg96778 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2009年12月21日 22:37 | |
No, I don't think that this issue is related, because it starts with another message: "Invalid thread state for this thread". |
|||
| msg96918 - (view) | Author: Nir Aides (nirai) (Python triager) | Date: 2009年12月27日 19:19 | |
Memory can be pre-allocated by thread_PyThread_start_new_thread() before thread is spawned. |
|||
| msg97480 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月09日 23:54 | |
Here I come with a patch! nirai idea was the good one: prealloc PyThreadState before creating the thread. Raise a MemoryError if the allocation fail, instead of raising a *fatal* Python error. Patch is quite simple and allow better error handling. |
|||
| msg97567 - (view) | Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) | Date: 2010年01月11日 01:07 | |
The patch looks good; the line tstate->thread_id = PyThread_get_thread_ident(); is needed because the tstate is created in the main thread, but used in another thread. |
|||
| msg97568 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月11日 01:21 | |
> The patch looks good I'm not sure about autoTLSkey value. PyThreadState_New() calls _PyGILState_NoteThreadState() which checks that autoTLSkey is not zero, but I don't know if autoTLSkey have the right value with my preallocation patch. |
|||
| msg97569 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月11日 01:41 | |
> I'm not sure about autoTLSkey value (...) After some tests (printf fun), it looks ok. -- There is another problem in _testcapi: test_thread_state() calls directly PyThread_start_new_thread() and the thread function calls PyGILState_Ensure(). PyGILState_Ensure() would then require to create a new thread state (call PyThreadState_New()) because it was not done by PyThread_start_new_thread(). On low memory condition, we hit the same bug here. Only thread and _testcapi modules calls directly PyThread_start_new_thread(). _*test*capi is reserved to tests, so I consider that we don't care about bugs under low memory condition in this module. |
|||
| msg97669 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2010年01月12日 22:33 | |
Running the tests in debug mode gives the following error: test_3_join_in_forked_from_thread (test.test_threading.ThreadJoinOnShutdown) ... Fatal Python error: Invalid thread state for this thread [21851 refs] FAIL [snip] ====================================================================== FAIL: test_3_join_in_forked_from_thread (test.test_threading.ThreadJoinOnShutdown) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/antoine/cpython/debug/Lib/test/test_threading.py", line 476, in test_3_join_in_forked_from_thread self._run_and_join(script) File "/home/antoine/cpython/debug/Lib/test/test_threading.py", line 412, in _run_and_join self.assertEqual(data, "end of main\nend of thread\n") AssertionError: 'end of main\n' != 'end of main\nend of thread\n' ---------------------------------------------------------------------- Ran 78 tests in 3.739s |
|||
| msg97678 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月13日 01:45 | |
> Running the tests in debug mode gives the following error: > ... Fatal Python error: Invalid thread state for this thread I tried all Lib/test/test_thread*py, but not in debug mode :-/ The problem is here: PyThreadState_New() -> _PyGILState_NoteThreadState() -> PyThread_set_key_value() -> find_key() and find_key() calls PyThread_get_thread_ident(), but the ident is not the right ident :-/ PyThreadState_New() should not call _PyGILState_NoteThreadState(), it should be done _in_ the thread. I wrote a new patch fixing the unit test. PyThreadState_New() is part of the public API, so I can't change its prototype. And _PyGILState_NoteThreadState() is a private function (use the "static" keyword). Because of that, I introduced two new functions: - PyThreadState_Prealloc(): like PyThreadState_New() but for thread preallocation, can be called outside the new state (from another thread) - PyThreadState_Init(): have to be called in the new thread to finish the thread state initialization, only required for state created by PyThreadState_Prealloc() (not for PyThreadState_New()) I tried all Lib/test/test_thread*.py tests in debug mode and all test now pass ;-) |
|||
| msg97714 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月13日 13:45 | |
Another problem with my patch! If initsite() calls PyGILState_Ensure(): assert(autoInterpreterState) fails because autoInterpreterState is NULL. _PyGILState_Init() have to be called before initsite(). I don't know where it should be called exactly. Why not just after the PyThreadState_New() (in Py_InitializeEx())? |
|||
| msg97715 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月13日 13:47 | |
> If initsite() calls PyGILState_Ensure() (...) Note: I was using gdb to track a bug on a debug build (--with-pydebug). I used "pyo" macro which calls _PyObject_Dump(), and _PyObject_Dump() calls PyGILState_Ensure() => assertion error. |
|||
| msg98106 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月21日 11:36 | |
Sum up of my patch: * it pass all test_thread*.py tests (tested with in pydebug mode) * it preallocates the thread state in the parent thread to be able to raise an error with PyErr_NoMemory() instead of Py_FatalError() * PyThreadState_Prealloc() doesn't call _PyGILState_NoteThreadState() because the thread ident is not correct in the parent thread * Call _PyGILState_NoteThreadState() in the new thread to finish the thread initialization * Py_InitializeEx() calls _PyGILState_Init() before initsite(), because initsite() may create a thread |
|||
| msg98562 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2010年01月30日 13:06 | |
I didn't test the patch but some comments:
- PyThreadState_Prealloc and PyThreadState_Init should probably be prefixed with an underscore, because there's no use for them outside of the interpreter
- _PyThreadState_New should be static. Besides, static functions usually don't get the "Py" in their name and are all lowercased, so something like "new_threadstate"
- the last change ("Py_InitializeEx() calls _PyGILState_Init() before initsite()") should be part of a separate patch (and issue?)
|
|||
| msg98563 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2010年01月30日 13:07 | |
Oh, and besides, you can use the -R option to regrtest to find out if there are any reference leaks (e.g. "-R 3:2:"). |
|||
| msg98637 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年01月31日 23:50 | |
> PyThreadState_Prealloc and PyThreadState_Init should (...) be prefixed with an underscore (...)
done
> _PyThreadState_New should be static (...) so something like "new_threadstate"
done
> the last change ("Py_InitializeEx() calls _PyGILState_Init() before initsite()") should be part of a separate patch (and issue?)
I'm unable to reproduce the bug related to this patch. I keep the patch somewhere in my disk, and I will open a new issue if I'm able to reproduce it :-)
> you can use the -R option to regrtest to find out if there are any reference leaks (e.g. "-R 3:2:")
I tried all test*thread*py. test_threadsignals leaks a reference... even without my patch, so I opened a new issue: #7825.
|
|||
| msg100358 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年03月03日 23:32 | |
Commited: r78638 (trunk), r78639 (py3k), r78640 (3.1). Keep the issue open to remember me that I have to backport it to 2.6 (the branch is frozen waiting for the 2.6.5 final version). |
|||
| msg101422 - (view) | Author: STINNER Victor (vstinner) * (Python committer) | Date: 2010年03月21日 13:33 | |
> Commited: r78638 (trunk) Backport done: r79199 (2.6). |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:56:55 | admin | set | github: 51793 |
| 2010年03月21日 13:33:03 | vstinner | set | status: open -> closed resolution: fixed messages: + msg101422 |
| 2010年03月03日 23:32:53 | vstinner | set | messages: + msg100358 |
| 2010年01月31日 23:51:06 | vstinner | set | files: - thread_prealloc_pystate-3.patch |
| 2010年01月31日 23:50:58 | vstinner | set | files:
+ thread_prealloc_pystate-4.patch messages: + msg98637 |
| 2010年01月30日 13:07:54 | pitrou | set | messages: + msg98563 |
| 2010年01月30日 13:06:50 | pitrou | set | messages: + msg98562 |
| 2010年01月21日 11:36:14 | vstinner | set | messages: + msg98106 |
| 2010年01月15日 00:13:08 | vstinner | set | files: - thread_prealloc_pystate-2.patch |
| 2010年01月15日 00:13:03 | vstinner | set | files: - thread_prealloc_pystate.patch |
| 2010年01月15日 00:12:58 | vstinner | set | files: + thread_prealloc_pystate-3.patch |
| 2010年01月13日 13:47:42 | vstinner | set | messages: + msg97715 |
| 2010年01月13日 13:45:08 | vstinner | set | messages: + msg97714 |
| 2010年01月13日 01:45:22 | vstinner | set | files:
+ thread_prealloc_pystate-2.patch messages: + msg97678 |
| 2010年01月12日 22:33:18 | pitrou | set | messages: + msg97669 |
| 2010年01月11日 01:41:40 | vstinner | set | messages: + msg97569 |
| 2010年01月11日 01:21:52 | vstinner | set | messages: + msg97568 |
| 2010年01月11日 01:07:51 | amaury.forgeotdarc | set | nosy:
+ amaury.forgeotdarc messages: + msg97567 |
| 2010年01月09日 23:54:25 | vstinner | set | files:
+ thread_prealloc_pystate.patch keywords: + patch messages: + msg97480 |
| 2009年12月27日 19:19:12 | nirai | set | messages: + msg96918 |
| 2009年12月27日 18:28:58 | nirai | set | nosy:
+ nirai |
| 2009年12月23日 23:06:15 | vstinner | set | title: multiprocessing.Pool(): Fatal Python error: PyEval_AcquireThread: NULL new thread state -> Fatal error on thread creation in low memory condition |
| 2009年12月21日 22:37:16 | vstinner | set | messages: + msg96778 |
| 2009年12月21日 16:46:07 | pitrou | set | messages: + msg96760 |
| 2009年12月20日 01:09:03 | vstinner | set | messages: + msg96658 |
| 2009年12月19日 16:26:06 | pitrou | set | nosy:
+ pitrou, jnoller messages: + msg96610 stage: test needed |
| 2009年12月19日 12:49:32 | vstinner | create | |