]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-112278: Improve error handling in wmi module and tests (GH-117818)
authorSteve Dower <steve.dower@python.org>
Mon, 15 Apr 2024 14:43:11 +0000 (15:43 +0100)
committerGitHub <noreply@github.com>
Mon, 15 Apr 2024 14:43:11 +0000 (15:43 +0100)
Lib/test/test_wmi.py
PC/_wmimodule.cpp

index bf8c52e646dc18d2799967574f3546791a163ac2..f667926d1f8ddfac4788626149d1d4e5d8a569ef 100644 (file)
@@ -14,11 +14,13 @@ def wmi_exec_query(query):
     # gh-112278: WMI maybe slow response when first call.
     try:
         return _wmi.exec_query(query)
+    except BrokenPipeError:
+        pass
     except WindowsError as e:
         if e.winerror != 258:
             raise
-        time.sleep(LOOPBACK_TIMEOUT)
-        return _wmi.exec_query(query)
+    time.sleep(LOOPBACK_TIMEOUT)
+    return _wmi.exec_query(query)
 
 
 class WmiTests(unittest.TestCase):
index 5ab6dcb032550bce0345b031578e6e378a4ed05c..22ed05276e6f0716972068397c5bb81e23755743 100644 (file)
@@ -279,9 +279,11 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
     // 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);
+        err = wait_event(data.initEvent, 1000);
+        if (!err) {
+            err = wait_event(data.connectEvent, 100);
+        }
     }
 
     while (!err) {
@@ -305,28 +307,33 @@ _wmi_exec_query_impl(PyObject *module, PyObject *query)
         CloseHandle(data.readPipe);
     }
 
-    // Allow the thread some time to clean up
-    switch (WaitForSingleObject(hThread, 100)) {
-    case WAIT_OBJECT_0:
-        // Thread ended cleanly
-        if (!GetExitCodeThread(hThread, (LPDWORD)&err)) {
-            err = GetLastError();
-        }
-        break;
-    case WAIT_TIMEOUT:
-        // Probably stuck - there's not much we can do, unfortunately
-        if (err == 0 || err == ERROR_BROKEN_PIPE) {
-            err = WAIT_TIMEOUT;
+    if (hThread) {
+        // Allow the thread some time to clean up
+        int thread_err;
+        switch (WaitForSingleObject(hThread, 100)) {
+        case WAIT_OBJECT_0:
+            // Thread ended cleanly
+            if (!GetExitCodeThread(hThread, (LPDWORD)&thread_err)) {
+                thread_err = GetLastError();
+            }
+            break;
+        case WAIT_TIMEOUT:
+            // Probably stuck - there's not much we can do, unfortunately
+            thread_err = WAIT_TIMEOUT;
+            break;
+        default:
+            thread_err = GetLastError();
+            break;
         }
-        break;
-    default:
+        // An error on our side is more likely to be relevant than one from
+        // the thread, but if we don't have one on our side we'll take theirs.
         if (err == 0 || err == ERROR_BROKEN_PIPE) {
-            err = GetLastError();
+            err = thread_err;
         }
-        break;
+
+        CloseHandle(hThread);
     }
 
-    CloseHandle(hThread);
     CloseHandle(data.initEvent);
     CloseHandle(data.connectEvent);
     hThread = NULL;