Skip to content

Commit

Permalink
Handle race condition in PdhUtil#PdhEnumObjectItems
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis committed May 31, 2022
1 parent 63ba30f commit e1dd416
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -13,6 +13,7 @@ Features
Bug Fixes
---------
* [#1438](https://github.com/java-native-access/jna/pull/1438): Handle arrays in structures with differing size - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1442](https://github.com/java-native-access/jna/issues/1442): Handle race condition in `c.s.j.p.win32.PdhUtil#PdhEnumObjectItems` - [@dbwiddis](https://github.com/dbwiddis).

Important Changes
-----------------
Expand Down
39 changes: 30 additions & 9 deletions contrib/platform/src/com/sun/jna/platform/win32/PdhUtil.java
Expand Up @@ -162,7 +162,9 @@ public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String
List<String> counters = new ArrayList<String>();
List<String> instances = new ArrayList<String>();

// Call once to get string lengths
// Call once to get counter and instance string lengths
// If zero on input and the object exists, the function returns PDH_MORE_DATA
// and sets these parameters to the required buffer size.
DWORDByReference pcchCounterListLength = new DWORDByReference(new DWORD(0));
DWORDByReference pcchInstanceListLength = new DWORDByReference(new DWORD(0));
int result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, null, pcchCounterListLength, null,
Expand All @@ -174,16 +176,35 @@ public static PdhEnumObjectItems PdhEnumObjectItems(String szDataSource, String
Memory mszCounterList = null;
Memory mszInstanceList = null;

if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}
// A race condition may exist for some instance lists such as processes or
// threads which may result in PDH_MORE_DATA.
do {
if (pcchCounterListLength.getValue().intValue() > 0) {
mszCounterList = new Memory(pcchCounterListLength.getValue().intValue() * CHAR_TO_BYTES);
}

if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}
if (pcchInstanceListLength.getValue().intValue() > 0) {
mszInstanceList = new Memory(pcchInstanceListLength.getValue().intValue() * CHAR_TO_BYTES);
}

result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);
result = Pdh.INSTANCE.PdhEnumObjectItems(szDataSource, szMachineName, szObjectName, mszCounterList,
pcchCounterListLength, mszInstanceList, pcchInstanceListLength, dwDetailLevel, 0);
if (result == Pdh.PDH_MORE_DATA) {
// If the specified size on input is greater than zero but less than the
// required size, you should not rely on the returned size to reallocate the
// buffer.
if (mszCounterList != null) {
long tooSmallSize = mszCounterList.size() / CHAR_TO_BYTES;
pcchCounterListLength.setValue(new DWORD(tooSmallSize + 1024));
mszCounterList.close();
}
if (mszInstanceList != null) {
long tooSmallSize = mszInstanceList.size() / CHAR_TO_BYTES;
pcchInstanceListLength.setValue(new DWORD(tooSmallSize + 1024));
mszInstanceList.close();
}
}
} while (result == Pdh.PDH_MORE_DATA);

if(result != WinError.ERROR_SUCCESS) {
throw new PdhException(result);
Expand Down

0 comments on commit e1dd416

Please sign in to comment.