Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Malformed PyImport_Inittab after re-initialization #88607

Closed
kryheb mannequin opened this issue Jun 17, 2021 · 10 comments
Closed

Malformed PyImport_Inittab after re-initialization #88607

kryheb mannequin opened this issue Jun 17, 2021 · 10 comments
Labels
3.9 only security fixes 3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir topic-C-API

Comments

@kryheb
Copy link
Mannequin

kryheb mannequin commented Jun 17, 2021

BPO 44441
Nosy @vstinner, @kryheb
PRs
  • bpo-44441: Set PyImport_Inittab to default on _PyImport_Fini2 #26767
  • bpo-44441: _PyImport_Fini2() resets PyImport_Inittab #26874
  • [3.10] bpo-44441: _PyImport_Fini2() resets PyImport_Inittab (GH-26874) #26877
  • [3.9] bpo-44441: _PyImport_Fini2() resets PyImport_Inittab (GH-26874) #26878
  • Files
  • inittab-bug.c: Source code to reproduce an issue
  • inittab-bug_no-threads.c: Source code to reproduce an issue
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2021-06-23.15:48:43.362>
    created_at = <Date 2021-06-17.10:14:12.876>
    labels = ['expert-C-API', 'library', '3.9', '3.10', '3.11']
    title = 'Malformed PyImport_Inittab after re-initialization'
    updated_at = <Date 2021-06-24.08:48:55.234>
    user = 'https://github.com/kryheb'

    bugs.python.org fields:

    activity = <Date 2021-06-24.08:48:55.234>
    actor = 'kryheb'
    assignee = 'none'
    closed = True
    closed_date = <Date 2021-06-23.15:48:43.362>
    closer = 'vstinner'
    components = ['Library (Lib)', 'C API']
    creation = <Date 2021-06-17.10:14:12.876>
    creator = 'kryheb'
    dependencies = []
    files = ['50115', '50125']
    hgrepos = []
    issue_num = 44441
    keywords = ['patch']
    message_count = 10.0
    messages = ['395985', '396300', '396385', '396404', '396405', '396414', '396427', '396428', '396429', '396462']
    nosy_count = 2.0
    nosy_names = ['vstinner', 'kryheb']
    pr_nums = ['26767', '26874', '26877', '26878']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue44441'
    versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

    @kryheb
    Copy link
    Mannequin Author

    kryheb mannequin commented Jun 17, 2021

    Hi all,

    I observed misbehavior trying to embed the Python interpreter into a C app.
    It seems that after re-initialization, PyImport_Inittab is malformed and points to the memory freed _PyImport_Fini2.

    Steps to reproduce:

    1. Append embedded module
    2. Initialize Python from config with run_filename
    3. Run main with an infinite loop
    4. Interrupt script execution with async call
    5. Finalize Python
    6. Repeat all above
    Observed behavior:
    The script is executed at first iteration, but re-initialization fails with an error:
    "
    Traceback (most recent call last):
      File "<frozen importlib._bootstrap>", line 1187, in _install_external_importers
    ModuleNotFoundError: No module named 'posix'

    Error: external importer setup failed
    "

    Head of modules list at fist run:
    ------ Modules: ------
    #0 'posix'
    #1 'errno'
    #2 'pwd'
    ----------------------
    and after re-initialization:
    ------ Modules: ------
    #0 'P ''
    #1 'errno'
    #2 'pwd'
    ----------------------

    An issue discovered on:
    Fedora 33
    gcc (GCC) 10.3.1 20210422 (Red Hat 10.3.1-1)
    python3-devel.x86_64 3.9.5-2.fc33

    Issue still exists on the latest main and on the rc 3.10
    Source code to reproduce an issue in attachment.

    Best regards,
    Krystian Heberlein

    @kryheb kryheb mannequin added 3.10 only security fixes 3.9 only security fixes stdlib Python modules in the Lib dir topic-C-API labels Jun 17, 2021
    @vstinner
    Copy link
    Member

    inittab-bug.c uses the Python C API in 3 threads:

    • Thread A (init_proc) calls Py_InitializeFromConfig()
    • Thread B (run_proc) calls Py_RunMain()
    • The main thread (main) calls Py_FinalizeEx()

    Problem: the thread B (run_proc) doesn't hold the GIL and so I get a fatal error with Python built in debug mode:
    ------------

    $ gcc inittab-bug.c -ggdb -pthread -lpython3.11d -L. -I. -I Include/
    $ PYTHONPATH=$PWD/Lib LD_LIBRARY_PATH=$PWD ./a.out
    ------ Modules: 

    #0 'posix'
    #1 'errno'
    #2 'pwd'
    ----------------------
    Could not find platform independent libraries <prefix>
    Could not find platform dependent libraries <exec_prefix>
    Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
    Run Python Script
    Fatal Python error: _PyMem_DebugMalloc: Python memory allocator called without holding the GIL
    Python runtime state: initialized

    Thread 0x00007f61ce5c1640 (most recent call first):
    <no Python frame>
    Abandon (core dumped)
    ------------

    If I remove the thread B (comment the comment), I get a similar error in the main thread which calls Py_FinalizeEx().

    Please fix your usage of the GIL. For example, you can try to use:

    Usually, Python initialization and Python finalization is done in the same thread, but another thread can use the Python C API if it acquires the GIL using PyGILState_Ensure().

    @kryheb
    Copy link
    Mannequin Author

    kryheb mannequin commented Jun 23, 2021

    Hi vstinner,

    I apologize for the inaccurate code sample.
    Please find a simplified example without threads inittab-bug_no-threads.c in attachments. Please notice that main.py has changed, there is no infinite loop anymore.

    Steps to reproduce:

    1. Append embedded module
    2. Initialize Python from config with run_filename
    3. Run main
    4. Finalize
    5. Repeat all above

    Observed behavior:
    The script is executed at the first iteration, but re-initialization fails with a segmentation fault:

    gdb) r
    Starting program: /home/kheb/proj/tmp/pyc/a.out 
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib64/libthread_db.so.1".
    Run Python Script
    >>> This is the python script
    Python Script completed (0)

    Program received signal SIGSEGV, Segmentation fault.
    __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
    65 VPCMPEQ (%rdi), %ymm0, %ymm1
    Missing separate debuginfos, use: dnf debuginfo-install libxcrypt-4.4.20-2.fc33.x86_64
    (gdb) bt
    #0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:65
    #1 0x00007ffff7d039f0 in PyUnicode_FromString (
    u=0xdddddddddddddddd <error: Cannot access memory at address 0xdddddddddddddddd>)
    at Objects/unicodeobject.c:2309
    #2 0x00007ffff7dbf049 in list_builtin_module_names () at ./Python/sysmodule.c:2056
    #3 0x00007ffff7dc1777 in _PySys_InitCore (tstate=tstate@entry=0x422ac0, sysdict=sysdict@entry=0x7fffea221070)
    at ./Python/sysmodule.c:2813
    #4 0x00007ffff7dc36ef in _PySys_Create (tstate=tstate@entry=0x422ac0, sysmod_p=sysmod_p@entry=0x7fffffffd9d8)
    at ./Python/sysmodule.c:3087
    #5 0x00007ffff7da9b32 in pycore_interp_init (tstate=0x422ac0) at Python/pylifecycle.c:824
    #6 0x00007ffff7da9c8e in pyinit_config (runtime=runtime@entry=0x7ffff7fbe820 <_PyRuntime>,
    tstate_p=tstate_p@entry=0x7fffffffdca8, config=config@entry=0x7fffffffdac0) at Python/pylifecycle.c:866
    #7 0x00007ffff7daba3e in pyinit_core (runtime=runtime@entry=0x7ffff7fbe820 <_PyRuntime>,
    src_config=src_config@entry=0x7fffffffdd40, tstate_p=tstate_p@entry=0x7fffffffdca8) at Python/pylifecycle.c:1029
    #8 0x00007ffff7dabb18 in Py_InitializeFromConfig (config=0x7fffffffdd40) at Python/pylifecycle.c:1214
    #9 0x00000000004012d3 in main (argc=1, argv=0x7fffffffdfc8) at inittab-bug_no-threads.c:45

    I hope this example helps.

    Best regards,
    Krystian

    @vstinner
    Copy link
    Member

    Thanks for inittab-bug_no-threads.c reproducer. I managed to reproduce the issue and I wrote PR 26767 to fix with a regression test.

    @vstinner
    Copy link
    Member

    Oh, I didn't notice your PR 26767 fix! Thanks. I wrote PR 26874 which includes the same fix, but adds also a regression test.

    @vstinner
    Copy link
    Member

    New changeset 489699c by Victor Stinner in branch 'main':
    bpo-44441: _PyImport_Fini2() resets PyImport_Inittab (GH-26874)
    489699c

    @vstinner
    Copy link
    Member

    New changeset 5ed7827 by Victor Stinner in branch '3.9':
    bpo-44441: _PyImport_Fini2() resets PyImport_Inittab (GH-26874) (GH-26878)
    5ed7827

    @vstinner
    Copy link
    Member

    New changeset ece3841 by Victor Stinner in branch '3.10':
    bpo-44441: _PyImport_Fini2() resets PyImport_Inittab (GH-26874) (GH-26877)
    ece3841

    @vstinner
    Copy link
    Member

    Thanks kryheb for your bug report, reproducer and your fix!

    The bug should now be fixed in 3.9, 3.10 and main branches.

    @vstinner vstinner added the 3.11 only security fixes label Jun 23, 2021
    @vstinner vstinner added the 3.11 only security fixes label Jun 23, 2021
    @kryheb
    Copy link
    Mannequin Author

    kryheb mannequin commented Jun 24, 2021

    Thanks vstinner for your help and for taking care of this case!

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.9 only security fixes 3.10 only security fixes 3.11 only security fixes stdlib Python modules in the Lib dir topic-C-API
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant