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

Appearance settings

Commit a955fd6

Browse filesBrowse files
authored
gh-112278: Disable WMI queries on Windows after they time out (GH-112658)
1 parent b2923a6 commit a955fd6
Copy full SHA for a955fd6

File tree

Expand file treeCollapse file tree

3 files changed

+44
-15
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+44
-15
lines changed

‎Lib/platform.py

Copy file name to clipboardExpand all lines: Lib/platform.py
+19-13Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@
118118
import sys
119119
import functools
120120
import itertools
121+
try:
122+
import _wmi
123+
except ImportError:
124+
_wmi = None
121125

122126
### Globals & Constants
123127

@@ -312,24 +316,26 @@ def _syscmd_ver(system='', release='', version='',
312316
version = _norm_version(version)
313317
return system, release, version
314318

315-
try:
316-
import _wmi
317-
except ImportError:
318-
def _wmi_query(*keys):
319+
320+
def _wmi_query(table, *keys):
321+
global _wmi
322+
if not _wmi:
319323
raise OSError("not supported")
320-
else:
321-
def _wmi_query(table, *keys):
322-
table = {
323-
"OS": "Win32_OperatingSystem",
324-
"CPU": "Win32_Processor",
325-
}[table]
324+
table = {
325+
"OS": "Win32_OperatingSystem",
326+
"CPU": "Win32_Processor",
327+
}[table]
328+
try:
326329
data = _wmi.exec_query("SELECT {} FROM {}".format(
327330
",".join(keys),
328331
table,
329332
)).split("\0")
330-
split_data = (i.partition("=") for i in data)
331-
dict_data = {i[0]: i[2] for i in split_data}
332-
return (dict_data[k] for k in keys)
333+
except OSError:
334+
_wmi = None
335+
raise OSError("not supported")
336+
split_data = (i.partition("=") for i in data)
337+
dict_data = {i[0]: i[2] for i in split_data}
338+
return (dict_data[k] for k in keys)
333339

334340

335341
_WIN32_CLIENT_RELEASES = [
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Reduce the time cost for some functions in :mod:`platform` on Windows if
2+
current user has no permission to the WMI.

‎PC/_wmimodule.cpp

Copy file name to clipboardExpand all lines: PC/_wmimodule.cpp
+23-2Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct _query_data {
4444
LPCWSTR query;
4545
HANDLE writePipe;
4646
HANDLE readPipe;
47+
HANDLE connectEvent;
4748
};
4849

4950

@@ -86,6 +87,9 @@ _query_thread(LPVOID param)
8687
NULL, NULL, 0, NULL, 0, 0, &services
8788
);
8889
}
90+
if (!SetEvent(data->connectEvent)) {
91+
hr = HRESULT_FROM_WIN32(GetLastError());
92+
}
8993
if (SUCCEEDED(hr)) {
9094
hr = CoSetProxyBlanket(
9195
services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
@@ -231,7 +235,8 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
231235

232236
Py_BEGIN_ALLOW_THREADS
233237

234-
if (!CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) {
238+
data.connectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
239+
if (!data.connectEvent || !CreatePipe(&data.readPipe, &data.writePipe, NULL, 0)) {
235240
err = GetLastError();
236241
} else {
237242
hThread = CreateThread(NULL, 0, _query_thread, (LPVOID*)&data, 0, NULL);
@@ -243,6 +248,21 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
243248
}
244249
}
245250

251+
// gh-112278: If current user doesn't have permission to query the WMI, the
252+
// function IWbemLocator::ConnectServer will hang for 5 seconds, and there
253+
// is no way to specify the timeout. So we use an Event object to simulate
254+
// a timeout.
255+
switch (WaitForSingleObject(data.connectEvent, 100)) {
256+
case WAIT_OBJECT_0:
257+
break;
258+
case WAIT_TIMEOUT:
259+
err = WAIT_TIMEOUT;
260+
break;
261+
default:
262+
err = GetLastError();
263+
break;
264+
}
265+
246266
while (!err) {
247267
if (ReadFile(
248268
data.readPipe,
@@ -265,7 +285,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
265285
}
266286

267287
// Allow the thread some time to clean up
268-
switch (WaitForSingleObject(hThread, 1000)) {
288+
switch (WaitForSingleObject(hThread, 100)) {
269289
case WAIT_OBJECT_0:
270290
// Thread ended cleanly
271291
if (!GetExitCodeThread(hThread, (LPDWORD)&err)) {
@@ -286,6 +306,7 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
286306
}
287307

288308
CloseHandle(hThread);
309+
CloseHandle(data.connectEvent);
289310
hThread = NULL;
290311

291312
Py_END_ALLOW_THREADS

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.