Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Lingering Subinterpreter Subthread Keeps Program From Exiting #113146

Closed as duplicate of#128639
Labels
3.12only security fixes3.13bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-subinterpreterstype-bugAn unexpected behavior, bug, or error
@ericsnowcurrently

Description

@ericsnowcurrently

Bug report

Steps:

  1. create a subinterpreter
  2. in it, start a subthread that takes one or more seconds to finish
  3. wait for that subthread to finish

One would expect execution to flow as follows:

main interpreter
main thread
subinterpreter
main thread
subinterpreter
subthread
1runtime init
2run script
3create subinterpreter
4init
5run code
6start subthreadrun code
7exit script(run code)
8begin runtime fini(run code)
9begin fini(run code)
10wait for subthread(run code)
11(wait for subthread)done
12finish fini
13finish fini
14exit

However, that isn't what's happening. Instead, at some point the subthread stops executing (without error) and the process effectively hangs (but can be stopped with Ctrl-C).

Script:
print('START: thread 0 (interp 0) - executing')importatexitimportthreadingfromtest.supportimportinterpretersdefnotify_before_thread_shutdown():print('START: thread 0 (interp 0) - waiting for non-daemon threads')threading._register_atexit(notify_before_thread_shutdown)defnotify_after_thread_shutdown():print('END:   thread 0 (interp 0) - waiting for non-daemon threads')atexit.register(notify_after_thread_shutdown)interp=interpreters.create()deftask():print('START: thread 1 (interp 0) - executing')interp.exec_sync("""if True:        print('START: thread 1 (interp 1) - executing')        import atexit        import threading        def notify_before_thread_shutdown():            print('START: thread 0 (interp 1) - waiting for non-daemon threads')        threading._register_atexit(notify_before_thread_shutdown)        def notify_after_thread_shutdown():            print('END:   thread 0 (interp 1) - waiting for non-daemon threads')        atexit.register(notify_after_thread_shutdown)        def task():            print('START: thread 2 (interp 1) - executing')            import time            for i in range(1, 11):                if i == 6:                    print(' ', end='', flush=True)                print('.', end='', flush=True)                time.sleep(0.1)            print(flush=True)            print('END:   thread 2 (interp 1) - executing')        t = threading.Thread(target=task)        t.start()        # t.join() here makes the problem go away.        print('END:   thread 1 (interp 1) - executing')    """)print('END:   thread 1 (interp 0) - executing')t=threading.Thread(target=task)t.start()t.join()# interp.close() here makes the problem go away.# time.sleep(1) here makes the problem go away.print('END:   thread 0 (interp 0) - executing')

Expected output:

START: thread 0 (interp 0) - executingSTART: thread 1 (interp 0) - executingSTART: thread 1 (interp 1) - executingSTART: thread 2 (interp 1) - executingEND:   thread 1 (interp 1) - executingEND:   thread 1 (interp 0) - executingEND:   thread 0 (interp 0) - executingSTART: thread 0 (interp 0) - waiting for non-daemon threadsEND:   thread 0 (interp 0) - waiting for non-daemon threadsSTART: thread 0 (interp 1) - waiting for non-daemon threads..... .....END:   thread 2 (interp 1) - executingEND:   thread 0 (interp 1) - waiting for non-daemon threads

Expected output:

START: thread 0 (interp 0) - executingSTART: thread 1 (interp 0) - executingSTART: thread 1 (interp 1) - executingSTART: thread 2 (interp 1) - executingEND:   thread 1 (interp 1) - executingEND:   thread 1 (interp 0) - executingEND:   thread 0 (interp 0) - executingSTART: thread 0 (interp 0) - waiting for non-daemon threadsEND:   thread 0 (interp 0) - waiting for non-daemon threadsSTART: thread 0 (interp 1) - waiting for non-daemon threads

I'm fairly sure I know what the problem is: our hack for dealing with daemon threads. Currently, between steps 8 and 9 above, we mark the runtime as finalizing. Any threads (regardless of interpreter) are more or less immediately killed.

However, as far as the threading module is concerned, they are still valid and running and will never stop. This isn't a problem for the main interpreter because at that point it already waited for it's own non-daemon threads to finish.

Thisis a problem for subinterpreters because they don't wait fortheir non-daemon threads to finish until later. Thus we end up waiting forever at step 10.

The solution? Immediately after waiting for non-daemon threads in step 8, finalize all subinterpreters. Alternately, we could make sure we're only killing daemon threads with our hack (e.g. don't use a global "finalizing" check).

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.12only security fixes3.13bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)topic-subinterpreterstype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp