Extend SystemProcess API Implementation to Windows - #7845
Conversation
|
@keithc-ca - Please review |
| /* | ||
| * Fallback: Use Toolhelp32Snapshot to retrieve process name for restricted/system processes. | ||
| */ | ||
| static const char * | ||
| getProcessNameFallback(DWORD pid, char *buffer, size_t bufferSize) | ||
| { | ||
| HANDLE hSnap = NULL; | ||
| PROCESSENTRY32 pe; | ||
| pe.dwSize = sizeof(PROCESSENTRY32); | ||
| hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | ||
| if (hSnap != INVALID_HANDLE_VALUE) { | ||
| if (Process32First(hSnap, &pe)) { | ||
| do { | ||
| if (pe.th32ProcessID == pid) { | ||
| strncpy(buffer, pe.szExeFile, bufferSize - 1); | ||
| buffer[bufferSize - 1] = '\0'; | ||
| break; | ||
| } | ||
| } while (Process32Next(hSnap, &pe)); | ||
| } | ||
| CloseHandle(hSnap); | ||
| } | ||
| return buffer; | ||
| } |
There was a problem hiding this comment.
It's not clear to me that use of CreateToolhelp32Snapshot() is reasonable because a 32-bit process cannot retrieve information for a 64-bit processes.
There was a problem hiding this comment.
@keithc-ca - There are some system/protected processes - such as csrss, System, wininit, Registry Memory Compression etc. Attempting to access them with OpenProcess fails due to access denial and these do not have an executable path. In hotspot these processes are also listed as part of this event, hence had to use the fallback function CreateToolhelp32Snapshot to get the process name. I’ve tested this and is able to list these processes.
If these processes are not needed, I can remove the fallback.
| DWORD numProcesses = 0; | ||
| DWORD bufferSize = 1024; | ||
| DWORD i = 0; | ||
| HANDLE hProcess = NULL; |
There was a problem hiding this comment.
Please move this declaration to line 2156 - it's only used within that scope.
| } | ||
| processes = (DWORD *)portLibrary->mem_allocate_memory( | ||
| portLibrary, | ||
| bufferSize * sizeof(DWORD), |
There was a problem hiding this comment.
Please just use bufferSize throughout instead of bufferSize * sizeof(DWORD). If reasonable, you could change the initial value:
DWORD bufferSize = 1024 * sizeof(DWORD);| return (uintptr_t)(intptr_t)OMRPORT_ERROR_OPFAILED; | ||
| } | ||
| processes = (DWORD *)portLibrary->mem_allocate_memory( | ||
| portLibrary, |
There was a problem hiding this comment.
Excessive indentation (one tab too many).
| portLibrary, | ||
| processes, | ||
| bufferSize * sizeof(DWORD), | ||
| OMR_GET_CALLSITE(), | ||
| OMRMEM_CATEGORY_PORT_LIBRARY); |
| } | ||
| numProcesses = bytesReturned / sizeof(DWORD); | ||
| for (i = 0; i < numProcesses; i++) { | ||
| char exePath[MAX_PATH] = {0}; |
There was a problem hiding this comment.
Please don't initialize an array like this; instead after line 2156:
exePath[0] = '\0';| DWORD pid = processes[i]; | ||
| hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION, FALSE, pid); | ||
| if (NULL != hProcess) { | ||
| if (0 == QueryFullProcessImageNameA(hProcess, 0, exePath, &pathLen)) { |
There was a problem hiding this comment.
Please use QueryFullProcessImageName() instead of QueryFullProcessImageNameA().
| getProcessNameFallback(pid, exePath, MAX_PATH); | ||
| } | ||
| /* Skip entries with no name. */ | ||
| if (exePath[0] == '\0') { |
There was a problem hiding this comment.
Constant on left of ==:
if ('\0' == exePath[0]) {| numProcesses = bytesReturned / sizeof(DWORD); | ||
| for (i = 0; i < numProcesses; i++) { | ||
| char exePath[MAX_PATH] = {0}; | ||
| DWORD pathLen = MAX_PATH; |
There was a problem hiding this comment.
The only use of MAX_PATH should be on line 2153; other places should use sizeof(exePath).
|
@keithc-ca - Addressed review comments. |
| } | ||
|
|
||
| /* | ||
| * Fallback: Use Toolhelp32Snapshot to retrieve process name for restricted/system processes. |
There was a problem hiding this comment.
I don't think we want to use this function at all: the documentation for CreateToolhelp32Snapshot() says 32-bit processes cannot retrieve information for a 64-bit process. If we do need to keep it, the comment should refer to the actual system call used.
There was a problem hiding this comment.
Ok, I have removed the fallback.
| PROCESSENTRY32 pe; | ||
| pe.dwSize = sizeof(PROCESSENTRY32); | ||
| hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | ||
| if (hSnap != INVALID_HANDLE_VALUE) { |
There was a problem hiding this comment.
Constant on the left of !=, please:
if (INVALID_HANDLE_VALUE != hSnap) {| { | ||
| HANDLE hSnap = NULL; | ||
| PROCESSENTRY32 pe; | ||
| pe.dwSize = sizeof(PROCESSENTRY32); |
There was a problem hiding this comment.
The rest of pe should be cleared:
memset(&pe, 0, sizeof(pe));
pe.dwSize = sizeof(pe);| } | ||
| CloseHandle(hSnap); | ||
| } | ||
| return buffer; |
There was a problem hiding this comment.
The return value is not actually used; suggest this should have void return type (if the function stays).
| portLibrary, | ||
| OMRPORT_ERROR_OPFAILED, | ||
| "Callback function is NULL."); | ||
| return (uintptr_t)(intptr_t)OMRPORT_ERROR_OPFAILED; |
There was a problem hiding this comment.
Line 2116 should be indented the same as line 2112.
| HANDLE hProcess = NULL; | ||
| hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION, FALSE, pid); |
There was a problem hiding this comment.
Please join these lines:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION, FALSE, pid);|
@keithc-ca - Addressed review comments. |
| char exePath[MAX_PATH]; | ||
| DWORD pathLen = sizeof(exePath); | ||
| DWORD pid = processes[i]; | ||
| HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_QUERY_INFORMATION, FALSE, pid); |
There was a problem hiding this comment.
This should request the minimum permissions necessary:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);| if (NULL != hProcess) { | ||
| if (0 == QueryFullProcessImageName(hProcess, 0, exePath, &pathLen)) { | ||
| CloseHandle(hProcess); | ||
| continue; | ||
| } | ||
| CloseHandle(hProcess); | ||
| } | ||
| /* Skip entries with no name. */ | ||
| if ('\0' == exePath[0]) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
The return type of QueryFullProcessImageName() is BOOL which should not be compared with 0. Suggest using pathLen to detect no name. Only one call to CloseHandle() is needed:
if (NULL == hProcess) {
continue;
}
if (!QueryFullProcessImageName(hProcess, 0, exePath, &pathLen)) {
pathLen = 0;
}
CloseHandle(hProcess);
/* Skip entries with no name. */
if (0 == pathLen) {
continue;
}
keithc-ca
left a comment
There was a problem hiding this comment.
I think this should be squashed. The commit message should mention QueryFullProcessImageName instead of QueryFullProcessImageNameA and should spell "Windows" consistently.
Use EnumProcesses and QueryFullProcessImageName to extract PID and executable paths on Windows. Signed-off-by: Sharanabasava <sharan16@in.ibm.com>
15786fc to
0e59648
Compare
|
jenkins build all |
babsingh
left a comment
There was a problem hiding this comment.
The Linux x86 and riscv64 failures are infra-related.
Use EnumProcesses and QueryFullProcessImageName to extract PID and executable paths on Windows.