diff options
author | AN Long <aisk@users.noreply.github.com> | 2023-12-08 16:52:22 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-08 16:52:22 (GMT) |
commit | 5a0137ca34deb6e1e2e890a52cb4b22d645c166b (patch) | |
tree | 788c9a176d91fb9c0079144dc22292e6243fe104 | |
parent | 4d1eea59bd26d329417cc2252f1c91b52d0f4a28 (diff) | |
download | cpython-5a0137ca34deb6e1e2e890a52cb4b22d645c166b.zip cpython-5a0137ca34deb6e1e2e890a52cb4b22d645c166b.tar.gz cpython-5a0137ca34deb6e1e2e890a52cb4b22d645c166b.tar.bz2 |
gh-112278: In _wmi, treat initialization timeout separately from connection timeout (GH-112878)
-rw-r--r-- | PC/_wmimodule.cpp | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/PC/_wmimodule.cpp b/PC/_wmimodule.cpp index 215350a..5ab6dcb 100644 --- a/PC/_wmimodule.cpp +++ b/PC/_wmimodule.cpp @@ -44,6 +44,7 @@ struct _query_data { LPCWSTR query; HANDLE writePipe; HANDLE readPipe; + HANDLE initEvent; HANDLE connectEvent; }; @@ -81,13 +82,16 @@ _query_thread(LPVOID param) IID_IWbemLocator, (LPVOID *)&locator ); } + if (SUCCEEDED(hr) && !SetEvent(data->initEvent)) { + hr = HRESULT_FROM_WIN32(GetLastError()); + } if (SUCCEEDED(hr)) { hr = locator->ConnectServer( bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &services ); } - if (!SetEvent(data->connectEvent)) { + if (SUCCEEDED(hr) && !SetEvent(data->connectEvent)) { hr = HRESULT_FROM_WIN32(GetLastError()); } if (SUCCEEDED(hr)) { @@ -193,6 +197,24 @@ _query_thread(LPVOID param) } +static DWORD +wait_event(HANDLE event, DWORD timeout) +{ + DWORD err = 0; + switch (WaitForSingleObject(event, timeout)) { + case WAIT_OBJECT_0: + break; + case WAIT_TIMEOUT: + err = WAIT_TIMEOUT; + break; + default: + err = GetLastError(); + break; + } + return err; +} + + /*[clinic input] _wmi.exec_query @@ -235,8 +257,11 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) Py_BEGIN_ALLOW_THREADS + data.initEvent = CreateEvent(NULL, TRUE, FALSE, NULL); data.connectEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!data.connectEvent || !CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) { + if (!data.initEvent || !data.connectEvent || + !CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) + { err = GetLastError(); } else { hThread = CreateThread(NULL, 0, _query_thread, (LPVOID*)&data, 0, NULL); @@ -251,16 +276,12 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) // gh-112278: If current user doesn't have permission to query the WMI, the // function IWbemLocator::ConnectServer will hang for 5 seconds, and there // is no way to specify the timeout. So we use an Event object to simulate - // a timeout. - switch (WaitForSingleObject(data.connectEvent, 100)) { - case WAIT_OBJECT_0: - break; - case WAIT_TIMEOUT: - err = WAIT_TIMEOUT; - break; - default: - err = GetLastError(); - break; + // a timeout. The initEvent will be set after COM initialization, it will + // take a longer time when first initialized. The connectEvent will be set + // after connected to WMI. + err = wait_event(data.initEvent, 1000); + if (!err) { + err = wait_event(data.connectEvent, 100); } while (!err) { @@ -306,6 +327,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query) } CloseHandle(hThread); + CloseHandle(data.initEvent); CloseHandle(data.connectEvent); hThread = NULL; |