From e8218be246af265ad3dc8d0121d9312a8c3816d3 Mon Sep 17 00:00:00 2001 From: Sylwester Lachiewicz Date: Mon, 26 Oct 2026 11:29:47 +0100 Subject: [PATCH] Give each mvn.cmd run its own temp directory (#13716) %RANDOM% is seeded from the clock once per cmd.exe, so mvn.cmd processes started in the same second named their jvm.config and version temp files alike. Since the JVM reads the jvm.config file as an @argfile and it is kept until the JVM exits, parallel builds ran with each other's JVM arguments. mkdir fails on an existing name, so a retry loop yields a private directory. --- apache-maven/src/assembly/maven/bin/mvn.cmd | 41 ++++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/apache-maven/src/assembly/maven/bin/mvn.cmd b/apache-maven/src/assembly/maven/bin/mvn.cmd index c36651e00787..c399d4a0b710 100644 --- a/apache-maven/src/assembly/maven/bin/mvn.cmd +++ b/apache-maven/src/assembly/maven/bin/mvn.cmd @@ -157,6 +157,7 @@ if not exist "%MAVEN_HOME%\bin\mvn.cmd" goto error @REM When only version info is requested, render the banner from a single @REM lightweight JVM (-XshowSettings) without starting Maven itself. set "FAST_VERSION=0" +set "VERSION_SETTINGS_DIR=" set "VERSION_SETTINGS_TEMP=" if defined IS_VERSION_AND_EXIT goto tryFastVersion if defined IS_SHOW_VERSION goto tryFastVersion @@ -165,10 +166,12 @@ goto javaGate :tryFastVersion if defined IS_VERBOSE goto javaGate if defined IS_MAIN_OVERRIDE goto javaGate -set "VERSION_SETTINGS_TEMP=%TEMP%\mvn-version-%RANDOM%-%RANDOM%.txt" +call :mkTempDir version VERSION_SETTINGS_DIR +if ERRORLEVEL 1 goto javaGate +set "VERSION_SETTINGS_TEMP=%VERSION_SETTINGS_DIR%\settings.txt" "%JAVACMD%" --enable-native-access=ALL-UNNAMED -XshowSettings:properties -version 2> "%VERSION_SETTINGS_TEMP%" if ERRORLEVEL 1 ( - del "%VERSION_SETTINGS_TEMP%" 2>nul + rd /s /q "%VERSION_SETTINGS_DIR%" 2>nul set "VERSION_SETTINGS_TEMP=" goto javaGate ) @@ -188,7 +191,7 @@ goto fastVersionDone :versionPrint call :printFastVersion "%VERSION_SETTINGS_TEMP%" -if defined VERSION_SETTINGS_TEMP del "%VERSION_SETTINGS_TEMP%" 2>nul +if defined VERSION_SETTINGS_DIR rd /s /q "%VERSION_SETTINGS_DIR%" 2>nul if defined IS_VERSION_AND_EXIT goto end set "MAVEN_VERSION_PRINTED=-Dmaven.version.printed=true" :fastVersionDone @@ -279,8 +282,10 @@ cd /d "%EXEC_DIR%" :endDetectBaseDir -rem Initialize JVM_CONFIG_ARGFILE_ARG to empty +rem Initialize to empty so values inherited from the environment are never used or deleted set "JVM_CONFIG_ARGFILE_ARG=" +set "JVM_CONFIG_DIR=" +set "JVM_CONFIG_TEMP=" if not exist "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadJvmConfig @@ -293,7 +298,12 @@ rem Why write to a temp file instead of capturing stdout via 'for /f ... in (`cm rem cmd.exe's child shell interprets special characters (pipes |, ampersands &, etc.) rem in the captured output — breaking values like -Dhttp.nonProxyHosts=de|*.de. -set "JVM_CONFIG_TEMP=%TEMP%\mvn-jvm-config-%RANDOM%-%RANDOM%.txt" +call :mkTempDir jvm-config JVM_CONFIG_DIR +if ERRORLEVEL 1 ( + echo ERROR: Could not create a temporary directory in %TEMP% for .mvn/jvm.config 1>&2 + exit /b 1 +) +set "JVM_CONFIG_TEMP=%JVM_CONFIG_DIR%\jvm.config.args" rem Debug logging (set MAVEN_DEBUG_SCRIPT=1 to enable) if defined MAVEN_DEBUG_SCRIPT ( @@ -316,9 +326,7 @@ if %JVM_CONFIG_EXIT% neq 0 ( echo ERROR: Failed to parse .mvn/jvm.config file 1>&2 echo jvm.config path: %MAVEN_PROJECTBASEDIR%\.mvn\jvm.config 1>&2 echo Java command: %JAVACMD% 1>&2 - if exist "%JVM_CONFIG_TEMP%" ( - del "%JVM_CONFIG_TEMP%" 2>nul - ) + rd /s /q "%JVM_CONFIG_DIR%" 2>nul exit /b 1 ) @@ -412,8 +420,8 @@ if defined MAVEN_DEBUG_SCRIPT ( %MAVEN_ARGS% ^ %* set JVM_CONFIG_EXIT_CODE=%ERRORLEVEL% -rem Cleanup the jvm.config temp file now that the JVM has exited (must be before @endlocal) -if defined JVM_CONFIG_TEMP del "%JVM_CONFIG_TEMP%" 2>nul +rem Cleanup the jvm.config temp directory now that the JVM has exited (must be before @endlocal) +if defined JVM_CONFIG_DIR rd /s /q "%JVM_CONFIG_DIR%" 2>nul if %JVM_CONFIG_EXIT_CODE% neq 0 goto error goto end @@ -527,3 +535,16 @@ echo Java version: %_JAVA_VERSION%, vendor: %_JAVA_VENDOR%, runtime: %_JAVA_HOME echo Default locale: %_LOCALE%, platform encoding: %_ENCODING%, time zone: %_TIMEZONE% echo OS name: "%_OS_NAME%", version: "%_OS_VERSION%", arch: "%_OS_ARCH%", family: "%_OS_FAMILY%" exit /b 0 + +:mkTempDir +@REM Creates a new, empty directory under %TEMP% and stores its path in the variable named by %2. +@REM %RANDOM% is seeded from the clock once per cmd.exe, so mvn.cmd processes started in the same +@REM second draw the same numbers. mkdir fails when the name is taken and the retry moves on to the +@REM next number, so concurrent builds never share a temp file. +set "_MKTEMP_TRIES=0" +:mkTempDirRetry +set /a _MKTEMP_TRIES+=1 +set "_MKTEMP_DIR=%TEMP%\mvn-%~1-%RANDOM%-%RANDOM%" +mkdir "%_MKTEMP_DIR%" 2>nul && (set "%~2=%_MKTEMP_DIR%" & exit /b 0) +if %_MKTEMP_TRIES% lss 100 goto mkTempDirRetry +exit /b 1