Skip to content

Commit

Permalink
#1152 / win / disk_io_counters(): DeviceIOControl errors were ignored…
Browse files Browse the repository at this point in the history
…; che return value and retry call on ERROR_INSUFFICIENT_BUFFER
  • Loading branch information
giampaolo committed Nov 11, 2017
1 parent 672253e commit ab90e4e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 29 deletions.
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

**Bug fixes**

- 1152_: [Windows] disk_io_counters() may return an empty dict.
- 1169_: [Linux] users() "hostname" returns username instead. (patch by
janderbrain)
- 1172_: [Windows] `make test` does not work.
Expand Down
69 changes: 40 additions & 29 deletions psutil/_psutil_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,9 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
char szDevice[MAX_PATH];
char szDeviceDisplay[MAX_PATH];
int devNum;
int i;
size_t ioctrlSize;
BOOL WINAPI ret;
PyObject *py_retdict = PyDict_New();
PyObject *py_tuple = NULL;

Expand All @@ -2380,39 +2383,47 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum);
hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);

if (hDevice == INVALID_HANDLE_VALUE)
continue;
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
&diskPerformance, sizeof(diskPerformance),
&dwSize, NULL))
{
sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%d", devNum);
py_tuple = Py_BuildValue(
"(IILLKK)",
diskPerformance.ReadCount,
diskPerformance.WriteCount,
diskPerformance.BytesRead,
diskPerformance.BytesWritten,
// convert to ms:
// https://github.com/giampaolo/psutil/issues/1012
(unsigned long long)
(diskPerformance.ReadTime.QuadPart) / 10000000,
(unsigned long long)
(diskPerformance.WriteTime.QuadPart) / 10000000);
if (!py_tuple)
goto error;
if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple))
goto error;
Py_XDECREF(py_tuple);
}
else {
// XXX we might get here with ERROR_INSUFFICIENT_BUFFER when
// compiling with mingw32; not sure what to do.
// return PyErr_SetFromWindowsErr(0);
;;

i = 0;
ioctrlSize = sizeof(diskPerformance);
while (1) {
i += 1;
ret = DeviceIoControl(
hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance,
ioctrlSize, &dwSize, NULL);
if (ret != 0)
break; // OK!
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (i <= 1024) { // prevent looping forever
ioctrlSize *= 2;
continue;
}
}
PyErr_SetFromWindowsErr(0);
goto error;
}

sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%d", devNum);
py_tuple = Py_BuildValue(
"(IILLKK)",
diskPerformance.ReadCount,
diskPerformance.WriteCount,
diskPerformance.BytesRead,
diskPerformance.BytesWritten,
// convert to ms:
// https://github.com/giampaolo/psutil/issues/1012
(unsigned long long)
(diskPerformance.ReadTime.QuadPart) / 10000000,
(unsigned long long)
(diskPerformance.WriteTime.QuadPart) / 10000000);
if (!py_tuple)
goto error;
if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple))
goto error;
Py_XDECREF(py_tuple);

CloseHandle(hDevice);
}

Expand Down

0 comments on commit ab90e4e

Please sign in to comment.