Issue44436
Created on 2021-06-16 15:43 by vstinner, last changed 2022-04-11 14:59 by admin. This issue is now closed.
| Messages (5) | |||
|---|---|---|---|
| msg395939 - (view) | Author: STINNER Victor (vstinner) * ![]() |
Date: 2021-06-16 15:43 | |
_thread.start_new_thread() is implemented by calling _beginthreadex(). Currently, when the thread completes: PyThread_exit_thread() is called which calls "_endthreadex(0)" on Windows. I proposed to no longer call it explicitly in bpo-44434. _endthreadex() documentation says that the thread handle must be closed explicitly (with CloseHandle()), same applies for ExitThread(). "Unlike _endthread, the _endthreadex function does not close the thread handle, thereby allowing other threads to block on this one without fear that the handle will be freed out from under the system." _endthread() closes the thread handle, but Python uses _endthreadex(). Should Python be modified to close explicitly the thread handle once the thread terminated? _endthread() and _endthreadex() documentation: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/endthread-endthreadex?view=msvc-160 Example closing the thread handle in the thread which created the thread: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/beginthread-beginthreadex?view=msvc-160 Simplified code: --- hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID ); WaitForSingleObject( hThread, INFINITE ); CloseHandle( hThread ); --- Would it be safe to close the handle just after PyThread_start_new_thread() success? Or should it be done in the C function thread_run(), just before existing, CloseHandle(GetCurrentThread())? To debug this issue, GetHandleInformation() can be used to check if the handle is still open or not. For example, call os.get_handle_inheritable(handle) in Python. |
|||
| msg395944 - (view) | Author: Eryk Sun (eryksun) * ![]() |
Date: 2021-06-16 15:56 | |
> Would it be safe to close the handle just after PyThread_start_new_thread() > success? We already close the handle in PyThread_start_new_thread() in Python/thread_nt.h: if (hThread == 0) { // ... } else { dprintf(("%lu: PyThread_start_new_thread succeeded: %p\n", PyThread_get_thread_ident(), (void*)hThread)); CloseHandle(hThread); } |
|||
| msg395945 - (view) | Author: STINNER Victor (vstinner) * ![]() |
Date: 2021-06-16 15:57 | |
> CloseHandle(GetCurrentThread()) This is useless. GetCurrentThread() returns a pseudo handle. The GetCurrentThread() documentation says: "The pseudo handle need not be closed when it is no longer needed. Calling the CloseHandle function with this handle has no effect." |
|||
| msg395947 - (view) | Author: STINNER Victor (vstinner) * ![]() |
Date: 2021-06-16 16:01 | |
> [Windows] _thread.start_new_thread() should close the thread handle
So far, I'm not convinced that Python must be changed.
I modified my Python locally so thread_run() writes GetCurrentThread() to stderr.
Example:
---
SLEEP = 5
import ctypes
import _thread
import time
import os
HANDLE = ctypes.c_voidp
DWORD = ctypes.c_ulong
ResumeThread = ctypes.windll.kernel32.ResumeThread
ResumeThread.argtypes = (HANDLE,)
ResumeThread.restype = DWORD
SuspendThread = ctypes.windll.kernel32.SuspendThread
SuspendThread.argtypes = (HANDLE,)
SuspendThread.restype = DWORD
def func():
time.sleep(SLEEP)
print("--thread exit--")
def check_handle(handle):
x = SuspendThread(handle)
print(f"SuspendThread({handle}) -> {x}")
x = ResumeThread(handle)
print(f"ResumeThread({handle}) -> {x}")
handle = _thread.start_new_thread(func, ())
print(f"start_new_thread() -> {handle}")
check_handle(handle)
time.sleep(SLEEP+1)
check_handle(handle)
---
Output:
---
start_new_thread() -> 2436
SuspendThread(2436) -> 4294967295
ResumeThread(2436) -> 4294967295
thread_run: GetCurrentThread() -> -2
--thread exit--
SuspendThread(2436) -> 4294967295
ResumeThread(2436) -> 4294967295
---
It seems like the handle returned by _beginthreadex() cannot be used with SuspendThread() or ResumeThread(): both fail. GetHandleInformation() also fails on this handle (I tried os.get_handle_inheritable()).
|
|||
| msg395948 - (view) | Author: STINNER Victor (vstinner) * ![]() |
Date: 2021-06-16 16:03 | |
Eryk: > We already close the handle in PyThread_start_new_thread() in Python/thread_nt.h Oh right! I completely missed this call. Thanks for double checking the issue ;-) I close the issue as "not a bug". |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:59:46 | admin | set | github: 88602 |
| 2021-06-16 16:03:07 | vstinner | set | status: open -> closed resolution: not a bug messages: + msg395948 stage: resolved |
| 2021-06-16 16:01:21 | vstinner | set | messages: + msg395947 |
| 2021-06-16 15:57:49 | vstinner | set | messages: + msg395945 |
| 2021-06-16 15:56:25 | eryksun | set | messages: + msg395944 |
| 2021-06-16 15:43:23 | vstinner | create | |

