杀死自我分叉 JVM。 PING 超时已过
Killing self fork JVM. PING timeout elapsed
编辑:我只是想澄清一下,为了提出一个已知 objective 答案的问题,这个问题是,"Killing self fork JVM. PING timeout elapsed" 实际上是什么意思,例如什么在 ping 什么,为什么 failsafe 决定它应该退出测试过程?由于这是 Whosebug,请不要回复修复某些 VM 退出的建议,尤其是那些导致与我们在下面看到的行为不同的行为的建议。例如。控制台中没有 OutOfMemoryError,所以我不认为 VM 运行 堆外 space。如果您确实这样回答,SO 管理员可能会因此误解我的问题并将其锁定或关闭。
我们有时会在 CI 构建中出现 VM 崩溃,例如:
[INFO] Results:
[INFO]
[WARNING] Tests run: 8152, Failures: 0, Errors: 0, Skipped: 31
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-plugin:2.22.1:verify (integration-test) on project app_server: There are test failures.
[ERROR]
[ERROR] Please refer to /builds/App/Development/App/app_server/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] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /builds/App/Development/App/app_server && /usr/lib/jvm/java-1.8-openjdk/jre/bin/java -Xmx3g -jar /builds/App/Development/App/app_server/target/surefire/surefirebooter7662621916357034130.jar /builds/App/Development/App/app_server/target/surefire 2019-01-09T21-23-07_397-jvmRun1 surefire1770987927673067492tmp surefire_37459604808221437221tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] Crashed tests:
[ERROR] com.company.blah.blah.ITSomeIntegrationTests
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:954)
[ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
[ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.lang.reflect.Method.invoke(Method.java:498)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
(当然,"There are test failures" 是错误的,因为没有失败的测试。)
我首先想知道的是,failsafe 试图告诉我们什么?以下是我们收集的一些信息:
首先,没有堆栈转储或堆转储,但有 surefire 和 failsafe 留下的 .dump 文件。对于失败的项目,总是有一个 .dump 文件,如:
# Created at 2019-02-12T14:31:16.410
System.exit() or native command error interrupted process checker.
java.lang.IllegalStateException: Cannot use PPID 158 process information. Going to use NOOP events.
at org.apache.maven.surefire.booter.PpidChecker.checkProcessInfo(PpidChecker.java:155)
at org.apache.maven.surefire.booter.PpidChecker.isProcessAlive(PpidChecker.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:214)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
# Created at 2019-02-12T14:47:59.174
Killing self fork JVM. PING timeout elapsed.
(这是故障保护进程和 Maven 进程之间的通信故障吗?)
此外,我们在调用 System.exit() 时打印堆栈跟踪,并且在每次此类失败中它看起来像:
java.lang.Exception: System.exit() or similar method called:
at com.app.IntegrationTestSetup.checkPermission(IntegrationTestSetup.java:78)
at java.lang.SecurityManager.checkExit(SecurityManager.java:761)
at java.lang.Runtime.halt(Runtime.java:273)
at org.apache.maven.surefire.booter.ForkedBooter.kill(ForkedBooter.java:311)
at org.apache.maven.surefire.booter.ForkedBooter.kill(ForkedBooter.java:305)
at org.apache.maven.surefire.booter.ForkedBooter.access0(ForkedBooter.java:68)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:285)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
即一些 surefire 代码(在这种情况下由 failsafe 插件使用)杀死了 failsafe 进程(surefire / failsafe 启动的 JVM 用于在作为 Maven 进程子进程的进程中进行测试)。
我们正在使用 failsafe 和 surefire 的 2.22.1 版。
# mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T18:33:14Z)
Maven home: /usr/share/java/maven-3
Java version: 1.8.0_191, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-1.8-openjdk/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-45-generic", arch: "amd64", family: "unix"
我找到了两种方法来避免这个问题,但都不太令人满意。
- 将 surefire 降级到 2.18.1
- 限制测试中的日志输出。例如,将日志级别设置为 WARN 而不是 DEBUG。
不过,我真的很想知道这个问题的真正解决方案是什么。
所有这些都在 mailing list 中进行了讨论,但我将在下面进行总结。
背景
默认情况下(在我们的例子中),Maven,运行在一个 JVM 中,forks一个 child 进程 运行ning 另一个 JVM 到 运行 测试。 parent 通过 child 的 stdin
给出 child 命令。具体来说,parent 向 child 发送一个 NOOP 命令,让它知道它还活着。
回答
ForkedBooter.java 间接设置两个线程。 commandReader
通过 stdin
从 parent 进程读取命令。 listenToShutdownCommands
向 commandReader
添加一个侦听器,以便在收到 NOOP 命令时将 AtomicBoolean
pingDone
设置为 true
。 listenToShutdownCommands
还安排了一项工作 运行 每 30 秒做一次这样的事情(为便于阅读而修改):
boolean hasPing = pingDone.getAndSet( false );
if ( !hasPing ) {
exit( 1 );
log( "Killing self fork JVM. PING timeout elapsed." );
所以错误消息声称 child 没有从 parent 读取 NOOP。
错误原因
仅凭以上描述,您或许就能猜到是什么问题了。我添加了日志记录以查看我的情况发生了什么,发现有时会暂停几分钟,在此期间 commandReader
不会读取任何 NOOP(通常 pingJob
不会 运行任何一个)。当两人有时间 运行 时,pingJob
可能会在 commandReader
轮到之前连续两次 运行。
简单地说,此代码中没有任何内容可以确保 OS 将 运行 线程足够频繁地从 stdin 读取。一个线程中可能有 3m 的暂停,因为我们已经要求 OS 到 运行 十几个具有同等优先级的其他线程,所有线程都有事情要做——他们没有睡觉,为 IO 屈服或阻塞。我们有一个重量级测试,确实有几个 3m 的暂停,即使在 4 核处理器上也是如此。
编辑:我只是想澄清一下,为了提出一个已知 objective 答案的问题,这个问题是,"Killing self fork JVM. PING timeout elapsed" 实际上是什么意思,例如什么在 ping 什么,为什么 failsafe 决定它应该退出测试过程?由于这是 Whosebug,请不要回复修复某些 VM 退出的建议,尤其是那些导致与我们在下面看到的行为不同的行为的建议。例如。控制台中没有 OutOfMemoryError,所以我不认为 VM 运行 堆外 space。如果您确实这样回答,SO 管理员可能会因此误解我的问题并将其锁定或关闭。
我们有时会在 CI 构建中出现 VM 崩溃,例如:
[INFO] Results:
[INFO]
[WARNING] Tests run: 8152, Failures: 0, Errors: 0, Skipped: 31
...
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-plugin:2.22.1:verify (integration-test) on project app_server: There are test failures.
[ERROR]
[ERROR] Please refer to /builds/App/Development/App/app_server/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] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /builds/App/Development/App/app_server && /usr/lib/jvm/java-1.8-openjdk/jre/bin/java -Xmx3g -jar /builds/App/Development/App/app_server/target/surefire/surefirebooter7662621916357034130.jar /builds/App/Development/App/app_server/target/surefire 2019-01-09T21-23-07_397-jvmRun1 surefire1770987927673067492tmp surefire_37459604808221437221tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] Crashed tests:
[ERROR] com.company.blah.blah.ITSomeIntegrationTests
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
[ERROR] at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR] at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR] at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR] at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR] at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR] at org.apache.maven.cli.MavenCli.execute(MavenCli.java:954)
[ERROR] at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
[ERROR] at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.lang.reflect.Method.invoke(Method.java:498)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
[ERROR] at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
(当然,"There are test failures" 是错误的,因为没有失败的测试。)
我首先想知道的是,failsafe 试图告诉我们什么?以下是我们收集的一些信息:
首先,没有堆栈转储或堆转储,但有 surefire 和 failsafe 留下的 .dump 文件。对于失败的项目,总是有一个 .dump 文件,如:
# Created at 2019-02-12T14:31:16.410
System.exit() or native command error interrupted process checker.
java.lang.IllegalStateException: Cannot use PPID 158 process information. Going to use NOOP events.
at org.apache.maven.surefire.booter.PpidChecker.checkProcessInfo(PpidChecker.java:155)
at org.apache.maven.surefire.booter.PpidChecker.isProcessAlive(PpidChecker.java:124)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:214)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
# Created at 2019-02-12T14:47:59.174
Killing self fork JVM. PING timeout elapsed.
(这是故障保护进程和 Maven 进程之间的通信故障吗?)
此外,我们在调用 System.exit() 时打印堆栈跟踪,并且在每次此类失败中它看起来像:
java.lang.Exception: System.exit() or similar method called:
at com.app.IntegrationTestSetup.checkPermission(IntegrationTestSetup.java:78)
at java.lang.SecurityManager.checkExit(SecurityManager.java:761)
at java.lang.Runtime.halt(Runtime.java:273)
at org.apache.maven.surefire.booter.ForkedBooter.kill(ForkedBooter.java:311)
at org.apache.maven.surefire.booter.ForkedBooter.kill(ForkedBooter.java:305)
at org.apache.maven.surefire.booter.ForkedBooter.access0(ForkedBooter.java:68)
at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:285)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
即一些 surefire 代码(在这种情况下由 failsafe 插件使用)杀死了 failsafe 进程(surefire / failsafe 启动的 JVM 用于在作为 Maven 进程子进程的进程中进行测试)。
我们正在使用 failsafe 和 surefire 的 2.22.1 版。
# mvn -v
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-17T18:33:14Z)
Maven home: /usr/share/java/maven-3
Java version: 1.8.0_191, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-1.8-openjdk/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.15.0-45-generic", arch: "amd64", family: "unix"
我找到了两种方法来避免这个问题,但都不太令人满意。
- 将 surefire 降级到 2.18.1
- 限制测试中的日志输出。例如,将日志级别设置为 WARN 而不是 DEBUG。
不过,我真的很想知道这个问题的真正解决方案是什么。
所有这些都在 mailing list 中进行了讨论,但我将在下面进行总结。
背景
默认情况下(在我们的例子中),Maven,运行在一个 JVM 中,forks一个 child 进程 运行ning 另一个 JVM 到 运行 测试。 parent 通过 child 的 stdin
给出 child 命令。具体来说,parent 向 child 发送一个 NOOP 命令,让它知道它还活着。
回答
ForkedBooter.java 间接设置两个线程。 commandReader
通过 stdin
从 parent 进程读取命令。 listenToShutdownCommands
向 commandReader
添加一个侦听器,以便在收到 NOOP 命令时将 AtomicBoolean
pingDone
设置为 true
。 listenToShutdownCommands
还安排了一项工作 运行 每 30 秒做一次这样的事情(为便于阅读而修改):
boolean hasPing = pingDone.getAndSet( false );
if ( !hasPing ) {
exit( 1 );
log( "Killing self fork JVM. PING timeout elapsed." );
所以错误消息声称 child 没有从 parent 读取 NOOP。
错误原因
仅凭以上描述,您或许就能猜到是什么问题了。我添加了日志记录以查看我的情况发生了什么,发现有时会暂停几分钟,在此期间 commandReader
不会读取任何 NOOP(通常 pingJob
不会 运行任何一个)。当两人有时间 运行 时,pingJob
可能会在 commandReader
轮到之前连续两次 运行。
简单地说,此代码中没有任何内容可以确保 OS 将 运行 线程足够频繁地从 stdin 读取。一个线程中可能有 3m 的暂停,因为我们已经要求 OS 到 运行 十几个具有同等优先级的其他线程,所有线程都有事情要做——他们没有睡觉,为 IO 屈服或阻塞。我们有一个重量级测试,确实有几个 3m 的暂停,即使在 4 核处理器上也是如此。