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.

classification
Title: C APIs called without GIL in PyOS_Readline
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.10, Python 3.9, Python 3.8
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: serhiy.storchaka, vstinner, xiang.zhang
Priority: normal Keywords:

Created on 2017-08-26 04:51 by xiang.zhang, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (6)
msg300862 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-08-26 04:51
When debugging our project I find something interesting. In PyOS_Readline it releases the GIL and delegate its job to PyOS_ReadlineFunctionPointer, which could be call_readline or PyOS_StdioReadline(I don't find where vms__StdioReadline is defined). But in the two functions, they use some C APIs like PyMem_Malloc/MALLOC, PyErr_SetString which need guarded by GIL. I don't understand why not doing find-grained lock control in call_readline or PyOS_StdioReadline since the code is ancient. :-(

I find this because our project makes test_cmd_line fail with `echo "Timer\n" | python -i -m timeit -n 1`.
msg300935 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2017-08-28 04:50
AFAIK PyMem_Malloc/MALLOC can be used with released GIL.
msg300936 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-08-28 05:01
In pymem.h, it's stated that "The GIL must be held when using these APIs". I think the reason is when PYMALLOC_DEBUG is defined, they finally delegate to PyObject_Malloc.

Victor must be familiar with them since once he proposed to remote the restriction: https://mail.python.org/pipermail/python-dev/2013-June/126822.html.
msg300945 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2017-08-28 09:32
You must hold the GIL to call PyMem_Malloc(). A debug assert should be
raised if you don't hold the GIL since Python 3.6 with PYTHONMALLOC=debug.

Call PyMem_RawMalloc().

I fixed Python 3, no?

For Python 2, in practice you can call PyMem_Malloc() without holding the
GIL, it's just malloc() which is thread safe.
msg300948 - (view) Author: Xiang Zhang (xiang.zhang) * (Python committer) Date: 2017-08-28 10:28
>>> I fixed Python 3, no?

Yes. In Python3 they are replaced by PyMem_RawMalloc. But it's not only PyMem_Malloc, there are also PyErr_SetString, PyErr_NoMemory, even in Python3.

BTW, even in Python3, when memory allocators are in debug mode, it finally calls bumpserialno, which IIUC, is not thread safe. But of course it's another issue.

>>> For Python 2, in practice you can call PyMem_Malloc() without holding the GIL, it's just malloc() which is thread safe.

Hmm, I know it. But it's not stated in the doc they are thread safe, I am not sure assuming this is suitable. An example is https://github.com/psycopg/psycopg2/issues/110.
msg372329 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2020-06-25 09:45
I fixed this issue in bpo-40826, especially with this change:

commit c353764fd564e401cf47a5d9efab18c72c60014e
Author: Victor Stinner <vstinner@python.org>
Date:   Mon Jun 1 20:59:35 2020 +0200

    bpo-40826: Fix GIL usage in PyOS_Readline() (GH-20579)
    
    Fix GIL usage in PyOS_Readline(): lock the GIL to set an exception.
    
    Pass tstate to my_fgets() and _PyOS_WindowsConsoleReadline(). Cleanup
    these functions.
History
Date User Action Args
2022-04-11 14:58:51adminsetgithub: 75463
2020-06-25 09:45:27vstinnersetstatus: open -> closed
versions: + Python 3.8, Python 3.9, Python 3.10, - Python 2.7, Python 3.6, Python 3.7
messages: + msg372329

resolution: fixed
stage: needs patch -> resolved
2017-08-28 10:28:41xiang.zhangsetmessages: + msg300948
2017-08-28 09:32:53vstinnersetmessages: + msg300945
2017-08-28 05:01:36xiang.zhangsetmessages: + msg300936
2017-08-28 04:50:22serhiy.storchakasetmessages: + msg300935
2017-08-28 02:28:22xiang.zhangsetstage: needs patch
versions: + Python 3.6, Python 3.7
2017-08-26 06:21:08serhiy.storchakasetnosy: + vstinner, serhiy.storchaka
2017-08-26 04:51:13xiang.zhangcreate