This is an automated email from the ASF dual-hosted git repository.
olamy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-surefire.git
The following commit(s) were added to refs/heads/master by this push:
new 688f8c463 Use PowerShell instead of WMIC for detecting zombie process
on Windows (#3258)
688f8c463 is described below
commit 688f8c46390a0d495a0c4169c873389b9c9b21b6
Author: jbliznak <[email protected]>
AuthorDate: Mon Feb 9 22:05:11 2026 +0100
Use PowerShell instead of WMIC for detecting zombie process on Windows
(#3258)
* Use PowerShell instead of WMIC for detecting zombie process on Windows
WMIC is not available in recent Windows versions.
The new solution with PowerShell should work for Windows 8 and newer
and Windows Server 2012 and newer.
The change is deliberately as small as possible, leaving most
of the old WMIC handling in place because there is a plan to deprecate
this class anyway.
On performance note: executing the check via PowerShell is notably
slower than with WMIC (low hundreds of millis vs tens of millis).
However, since this check is used only to detect zombie process
and only once per tens of seconds, this will hopefully be good enough.
Much better and faster implementation could be done once the minimal
supported Java moves to 9 or later via ProcessHandle, until then
this should do.
---
.github/workflows/maven-verify.yml | 2 +-
.../apache/maven/surefire/booter/PpidChecker.java | 32 ++++++++++++++--------
.../maven/surefire/booter/PpidCheckerTest.java | 10 +++----
3 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/.github/workflows/maven-verify.yml
b/.github/workflows/maven-verify.yml
index 51567b81d..2d827a276 100644
--- a/.github/workflows/maven-verify.yml
+++ b/.github/workflows/maven-verify.yml
@@ -49,4 +49,4 @@ jobs:
!**/hs_err_pid*
!surefire-its/target/ConsoleOutputIT_*/target/surefire-reports/*-jvmRun*-events.bin
timeout-minutes: 600
- os-matrix: '[ "ubuntu-latest", "windows-2022", "macos-latest" ]'
+ os-matrix: '[ "ubuntu-latest", "windows-latest", "macos-latest" ]'
diff --git
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
index 2c836ea21..b8891e822 100644
---
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
+++
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/PpidChecker.java
@@ -70,9 +70,9 @@ final class PpidChecker {
IS_OS_WINDOWS ? createWindowsCreationDateFormat() : null;
private static final String WMIC_CREATION_DATE = "CreationDate";
private static final String WINDOWS_SYSTEM_ROOT_ENV = "SystemRoot";
- private static final String RELATIVE_PATH_TO_WMIC = "System32\\Wbem";
- private static final String SYSTEM_PATH_TO_WMIC =
- "%" + WINDOWS_SYSTEM_ROOT_ENV + "%\\" + RELATIVE_PATH_TO_WMIC +
"\\";
+ private static final String RELATIVE_PATH_TO_POWERSHELL =
"System32\\WindowsPowerShell\\v1.0";
+ private static final String SYSTEM_PATH_TO_POWERSHELL =
+ System.getenv(WINDOWS_SYSTEM_ROOT_ENV) + "\\" +
RELATIVE_PATH_TO_POWERSHELL + "\\";
private static final String PS_ETIME_HEADER = "ELAPSED";
private static final String PS_PID_HEADER = "PID";
@@ -192,6 +192,7 @@ ProcessInfo windows() {
@Nonnull
ProcessInfo consumeLine(String line, ProcessInfo
previousProcessInfo) throws Exception {
if (previousProcessInfo.isInvalid() && !line.isEmpty()) {
+ // we still use WMIC output format even though we now use
PowerShell to produce it
if (hasHeader) {
// now the line is CreationDate, e.g.
20180406142327.741074+120
if (line.length() != WMIC_CREATION_DATE_VALUE_LENGTH) {
@@ -210,13 +211,19 @@ ProcessInfo consumeLine(String line, ProcessInfo
previousProcessInfo) throws Exc
return previousProcessInfo;
}
};
- String wmicPath = hasWmicStandardSystemPath() ? SYSTEM_PATH_TO_WMIC :
"";
- return reader.execute(
- "CMD",
- "/A",
- "/X",
- "/C",
- wmicPath + "wmic process where (ProcessId=" + ppid + ") get "
+ WMIC_CREATION_DATE);
+
+ String psPath = hasPowerShellStandardSystemPath() ?
SYSTEM_PATH_TO_POWERSHELL : "";
+ // mimic output format of the original check:
+ // wmic process where (ProcessId=<ppid>) get CreationDate
+ String psCommand = String.format(
+ "Add-Type -AssemblyName System.Management; "
+ + "$p = Get-CimInstance Win32_Process -Filter
'ProcessId=%2$s'; "
+ + "if ($p) { "
+ + " Write-Output '%1$s'; "
+ + "
[System.Management.ManagementDateTimeConverter]::ToDmtfDateTime($p.CreationDate)
"
+ + "}",
+ WMIC_CREATION_DATE, ppid);
+ return reader.execute(psPath + "powershell", "-NoProfile",
"-NonInteractive", "-Command", psCommand);
}
void destroyActiveCommands() {
@@ -254,9 +261,10 @@ private static boolean canExecuteStandardUnixPs() {
}
}
- private static boolean hasWmicStandardSystemPath() {
+ private static boolean hasPowerShellStandardSystemPath() {
String systemRoot = System.getenv(WINDOWS_SYSTEM_ROOT_ENV);
- return isNotBlank(systemRoot) && new File(systemRoot,
RELATIVE_PATH_TO_WMIC + "\\wmic.exe").isFile();
+ return isNotBlank(systemRoot)
+ && new File(systemRoot, RELATIVE_PATH_TO_POWERSHELL +
"\\powershell.exe").isFile();
}
static long fromDays(Matcher matcher) {
diff --git
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
index 78f35716f..5b05d1a46 100644
---
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
+++
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/PpidCheckerTest.java
@@ -365,15 +365,15 @@ public void shouldParseBusyboxHoursEtime() {
}
@Test
- public void shouldHaveSystemPathToWmicOnWindows() throws Exception {
+ public void shouldHaveSystemPathToPowerShellOnWindows() throws Exception {
assumeTrue(IS_OS_WINDOWS);
assumeThat(System.getenv("SystemRoot"), is(notNullValue()));
assumeThat(System.getenv("SystemRoot"), is(not("")));
- assumeTrue(new File(System.getenv("SystemRoot"),
"System32\\Wbem").isDirectory());
- assumeTrue(new File(System.getenv("SystemRoot"),
"System32\\Wbem\\wmic.exe").isFile());
- assertThat((Boolean) invokeMethod(PpidChecker.class,
"hasWmicStandardSystemPath"))
+ assumeTrue(new File(System.getenv("SystemRoot"),
"System32\\WindowsPowerShell\\v1.0").isDirectory());
+ assumeTrue(new File(System.getenv("SystemRoot"),
"System32\\WindowsPowerShell\\v1.0\\powershell.exe").isFile());
+ assertThat((Boolean) invokeMethod(PpidChecker.class,
"hasPowerShellStandardSystemPath"))
.isTrue();
- assertThat(new File(System.getenv("SystemRoot"),
"System32\\Wbem\\wmic.exe"))
+ assertThat(new File(System.getenv("SystemRoot"),
"System32\\WindowsPowerShell\\v1.0\\powershell.exe"))
.isFile();
}