You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by "Slawomir Jaranowski (Jira)" <ji...@apache.org> on 2022/12/19 14:42:00 UTC

[jira] [Closed] (SUREFIRE-2135) 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

     [ https://issues.apache.org/jira/browse/SUREFIRE-2135?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Slawomir Jaranowski closed SUREFIRE-2135.
-----------------------------------------
    Fix Version/s: 3.0.0-M8
       Resolution: Fixed

> 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
>             Fix For: 3.0.0-M8
>
>
> 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)