 ------
 Forked JVM Shutdown
 ------
 Tibor Digana <tibordigana@apache.org>
 ------
 September 2015
 ------
 
 ~~ Licensed to the Apache Software Foundation (ASF) under one
 ~~ or more contributor license agreements.  See the NOTICE file
 ~~ distributed with this work for additional information
 ~~ regarding copyright ownership.  The ASF licenses this file
 ~~ to you under the Apache License, Version 2.0 (the
 ~~ "License"); you may not use this file except in compliance
 ~~ with the License.  You may obtain a copy of the License at
 ~~
 ~~   http://www.apache.org/licenses/LICENSE-2.0
 ~~
 ~~ Unless required by applicable law or agreed to in writing,
 ~~ software distributed under the License is distributed on an
 ~~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 ~~ KIND, either express or implied.  See the License for the
 ~~ specific language governing permissions and limitations
 ~~ under the License.

 ~~ NOTE: For help with the syntax of this file, see:
 ~~ http://maven.apache.org/doxia/references/apt-format.html 

Shutdown of Forked JVM

* Embedded shutdown
  
  After the test-set has completed, the process executes
  <<<java.lang.System.exit(0)>>> which starts shutdown hooks. At this point
  the process may run next 30 seconds until all non daemon Threads die.
  After the period of time has elapsed, the process kills itself by
  <<<java.lang.Runtime.halt(0)>>>. The timeout of 30 seconds can be
  customized by configuration parameter <<<forkedProcessExitTimeoutInSeconds>>>.

* Pinging forked JVM

  << Since ${thisPlugin} Plugin 2.20.1 ping is platform dependent and fallbacks to old mechanism if PID of Maven
  process or platform is not recognized, native commands fail in Java. >>

  Simply the mechanism checks the <<< Maven PID >>> is still alive and it is not reused by OS in another application.
  If Maven process has died, the forked JVM is killed.

  << Implementation: >> The <<< Maven PID >>> is determined by:

   * Java 9 call <<< ProcessHandle.current().pid() >>>, or

   * resolving PID from <<< /proc/self/stat >>> on Linux and <<< /proc/curproc/status >>> on BSD, or

   * the JMX call <<< ManagementFactory.getRuntimeMXBean().getName() >>>.

   []

   On Unix like systems the process' uptime is determined by native command <<< (/usr)/bin/ps -o etime= -p [PID] >>>.

   On Windows the start time is determined using <<< wmic process where (ProcessId=[PID]) get CreationDate >>>
   in the forked JVM.


  << Since ${thisPlugin} Plugin 2.19 the old mechanism is significantly slower: >>

  The master process sends NOOP command to a forked JVM every 10 seconds.
  Forked JVM is waiting for the command every 20 seconds (changed to 30 seconds since version 2.20.1, see
  {{{https://issues.apache.org/jira/browse/SUREFIRE-1302}SUREFIRE-1302}}).
  If the master process is killed (received SIGKILL signal) or shutdown 
  (pressed CTRL+C, received SIGTERM signal), forked JVM is killed after
  timing out waiting period.


  NOTICE: After version <<<3.0.0-M4>>> this feature has to be enabled by setting the configuration
  parameter <<<enableProcessChecker>>> to <<<ping>>> or <<<all>>>.

* Shutdown of forked JVM by stopping the build

  After the master process of the build is shutdown by sending SIGTERM signal
  or pressing CTRL+C, the master process immediately sends SHUTDOWN command to
  every forked JVM. By default (configuration parameter <<<shutdown=testset>>>)
  forked JVM would not pick up a new test which means that the current
  test may still continue to run. The SIGTERM signal triggers Java shutdownhook
  which executes <<<java.lang.Process.destroy()>>> in the forked JVM (not always
  reliable depending on VM and OS).
  The parameter <<<shutdown>>> can be configured with other two values
  <<<exit>>> and <<<kill>>>. Using <<<exit>>> forked JVM executes
  <<<java.lang.System.exit(1)>>> after the master process has received SIGTERM.
  Using <<<kill>>> the JVM executes <<<java.lang.Runtime.halt(1)>>>, example:

+---+
<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>${project.groupId}</groupId>
        <artifactId>${project.artifactId}</artifactId>
        <version>${project.version}</version>
        <configuration>
          <shutdown>kill</shutdown>
        </configuration>
      </plugin>
    </plugins>
  </build>
  [...]
</project>
+---+


  NOTICE: After version <<<3.0.0-M4>>> this feature has to be enabled by setting the configuration
  parameter <<<enableProcessChecker>>> to <<<ping>>> or <<<native>>> or <<<all>>>.

* Shutdown of forked JVM after certain timeout

  Using parameter <<<forkedProcessTimeoutInSeconds>>> forked JVMs
  are killed separately after every individual process elapsed certain
  amount of time and the whole plugin fails with the error message:

  <<<There was a timeout in the fork>>>


* Crashed forked JVM caused listing the crashed test(s)

  After the JVM exited abruptly, the console lists the message <<<Crashed tests:>>> with a list of crashed tests if the
  entire test-set has not been yet completed. This happens if a test exited, killed JVM or a segmentation fault crashed
  JVM. In such cases you may be interested in dump files generated in reports directory, see {{{../faq.html#dumpfiles}FAQ}}.

