summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2017-11-12 01:47:20 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2017-11-12 01:47:20 +0100
commit988dcd737da2855bc3eb10904f46e6456a664f83 (patch)
tree2be30cc35d52374fcfdf2918048b090840c83bdc
parentab90e4e6ac73c249cf7aea7e92aec2b6a07ef041 (diff)
downloadpsutil-988dcd737da2855bc3eb10904f46e6456a664f83.tar.gz
#1152: (DeviceIOControl), skip disk on ERROR_INVALID_FUNCTION and ERROR_NOT_SUPPORTED
-rw-r--r--psutil/_psutil_windows.c25
-rwxr-xr-xpsutil/tests/test_system.py2
2 files changed, 25 insertions, 2 deletions
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index 7cf8f2c9..e28c12e3 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -2386,6 +2386,7 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
if (hDevice == INVALID_HANDLE_VALUE)
continue;
+ // DeviceIoControl() sucks!
i = 0;
ioctrlSize = sizeof(diskPerformance);
while (1) {
@@ -2396,11 +2397,32 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
if (ret != 0)
break; // OK!
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- if (i <= 1024) { // prevent looping forever
+ // Retry with a bigger buffer (+ limit for retries).
+ if (i <= 1024) {
ioctrlSize *= 2;
continue;
}
}
+ else if (GetLastError() == ERROR_INVALID_FUNCTION) {
+ // This happens on AppVeyor:
+ // https://ci.appveyor.com/project/giampaolo/psutil/build/
+ // 1364/job/ascpdi271b06jle3
+ // Assume it means we're dealing with some exotic disk
+ // and go on.
+ goto next;
+ }
+ else if (GetLastError() == ERROR_NOT_SUPPORTED) {
+ // Again, let's assume we're dealing with some exotic disk.
+ goto next;
+ }
+ // XXX: it seems we should also catch ERROR_INVALID_PARAMETER:
+ // https://sites.ualberta.ca/dept/aict/uts/software/openbsd/
+ // ports/4.1/i386/openafs/w-openafs-1.4.14-transarc/
+ // openafs-1.4.14/src/usd/usd_nt.c
+
+ // XXX: we can also bump into ERROR_MORE_DATA in which case
+ // (quoting doc) we're supposed to retry with a bigger buffer
+ // and specify a new "starting point", whatever it means.
PyErr_SetFromWindowsErr(0);
goto error;
}
@@ -2424,6 +2446,7 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
goto error;
Py_XDECREF(py_tuple);
+next:
CloseHandle(hDevice);
}
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 3485fb8f..2da4d60d 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -670,7 +670,7 @@ class TestSystemAPIs(unittest.TestCase):
@unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
'/proc/diskstats not available on this linux version')
- @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") # no visible disks
+ # @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") # no visible disks
def test_disk_io_counters(self):
def check_ntuple(nt):
self.assertEqual(nt[0], nt.read_count)