[
https://issues.apache.org/jira/browse/SUREFIRE-2135?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Slawomir Jaranowski reassigned SUREFIRE-2135:
---------------------------------------------
Assignee: Slawomir Jaranowski
> On Unix-like OS and JDK 18+ Surefire kills the forked JVM if PpidChecker is
> active and argLine is set to -Dfile.encoding=UTF-16
> -------------------------------------------------------------------------------------------------------------------------------
>
> Key: SUREFIRE-2135
> URL: https://issues.apache.org/jira/browse/SUREFIRE-2135
> Project: Maven Surefire
> Issue Type: Bug
> Components: process forking
> Affects Versions: 3.0.0-M4, 3.0.0-M5, 3.0.0-M6, 3.0.0-M7
> Environment: Unix-like OS, JDK 18 or higher
> Reporter: Andreas Pabst
> Assignee: Slawomir Jaranowski
> Priority: Major
>
> This breaks the continuous build on Java 18 and 19 because the integration
> test {{ConsoleOutputIT#properNewlinesAndEncodingWithDifferentEncoding}} fails.
> h3. Steps to reproduce
> A minimum project to reproduce the issue requires a unit test and the
> following surefire configuration:
> {code:xml}
> <build>
> <plugins>
> <plugin>
> <groupId>org.apache.maven.plugins</groupId>
> <artifactId>maven-surefire-plugin</artifactId>
> <version>3.0.0-M7</version>
> <configuration>
> <enableProcessChecker>all</enableProcessChecker>
> </configuration>
> </plugin>
> </plugins>
> </build>
> {code}
> The following output will be produced upon executing {{{}mvn test{}}}:
> {noformat}
> [ERROR] Failed to execute goal
> org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M7:test (default-test)
> on project myproject:
> [ERROR] Please refer to
> /home/ogapa/code/maven-samples/utf16/target/surefire-reports for the
> individual test results.
> [ERROR] Please refer to dump files (if any exist) [date].dump,
> [date]-jvmRun[N].dump and [date].dumpstream.
> [ERROR] The forked VM terminated without properly saying goodbye. VM crash or
> System.exit called?
> {noformat}
> with the following stacktrace
> {noformat}
> org.apache.maven.surefire.booter.SurefireBooterForkException: Error occurred
> in starting fork, check output in log
> at
> org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:635)
> at
> org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:311)
> at
> org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:268)
> at
> org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1334)
> at
> org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1167)
> at
> org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:931)
> at
> org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
> at
> org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2(MojoExecutor.java:370)
> at
> org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:351)
> at
> org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:215)
> at
> org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:171)
> at
> org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:163)
> at
> org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
> at
> org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
> at
> org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
> at
> org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
> at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:294)
> at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
> at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
> at org.apache.maven.cli.MavenCli.execute(MavenCli.java:960)
> at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:293)
> at org.apache.maven.cli.MavenCli.main(MavenCli.java:196)
> at
> java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
> at java.base/java.lang.reflect.Method.invoke(Method.java:577)
> at
> org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
> at
> org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
> at
> org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
> at
> org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
> {noformat}
> All versions between 3.0.0-M4 and 3.0.0-M7 are affected. I could not
> reproduce it with versions before 3.0.0-M4.
> h3. Root cause analysis
> In the log of the failed test the following line gives an indication as to
> what the cause is:
> {noformat}
> [ERROR] Surefire is going to kill self fork JVM. Maven process died.
> {noformat}
> _Note: There is a race condition. If the test is fast enough (< 20 ms), the
> build may actually be successful despite the attempted killing of the self
> fork JVM. The exit code of the mvn process is still 1 though, not 0._
> The above output is produced by the {{ForkedBooter}} class if
> {{PpidChecker#isProcessAlive}} returns false but the ping scheduler is not
> shut down yet.
> Debugging into {{PpidChecker}} I found the reason why
> {{PpidChecker#isProcessAlive}} returns false:
> The {{PpidChecker}} uses the command {{ps -o etime,pid <PID>}} to check if
> the elapsed time is still increasing, but if {{file.encoding}} is set to
> UTF-16, it fails to parse the {{ps}} output. Parsing fails because the
> {{java.util.Scanner}} it uses for that job is configured with
> {{Charset#defaultCharset}}, meaning it expects the {{InputStream}} of the
> {{ps}} output to produce UTF-16. It is however UTF-8 on basically all
> Unix-like systems.
> h3. So, how did this code work before Java 18?
> It didn't. The only reason this didn't surface before is that there was
> another bug that prevented the {{PpidChecker}} from even getting that far. In
> Java versions < 18 the {{ProcessBuilder#start}} call fails if
> {{file.encoding}} is set to UTF-16, with an exception message saying
> "java.io.IOException: Cannot run program "/bin/sh": error=2, No such file or
> directory" which leads to {{PpidChecker#isProcessAlive}} throwing an
> exception. That exception leads to the process check being aborted, but is
> then swallowed in the {{ForkedBooter}} class.
> The {{ProcessBuilder}} bug was apparently fixed in Java 18 which led to this
> problem surfacing.
> h3. Suggestion of a fix
> In Java 17 the additional system property {{native.encoding}} was
> [introduced|https://bugs.openjdk.org/browse/JDK-8266075]. Since we are
> dealing with the output of a native OS command, this is the correct encoding
> to use for this particular use case - if it is present.
> In case the system property is missing, we can use UTF-8 as a reasonable
> default since almost all modern Unix-like systems use UTF-8 as a system
> encoding by default.
> So, when configuring the {{java.util.Scanner}} it uses to parse the output of
> the {{ps}} command, I suggest the {{PpidChecker}} should configure it based
> on the system property {{native.encoding}} and fall back to UTF-8 if the
> system property is absent, i.e. in Java versions before 17.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)