1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 4244896
  27  * @summary Test for the various platform specific implementations of
  28  *          destroyForcibly.
  29  */
  30 
  31 import java.io.*;
  32 import java.util.ArrayList;
  33 import java.util.concurrent.TimeUnit;
  34 
  35 abstract class ProcessTest implements Runnable {
  36     ProcessBuilder bldr;
  37     Process p;
  38 
  39     public Process killProc(boolean force) throws Exception {
  40         if (force) {
  41             p.destroyForcibly();
  42         } else {
  43             p.destroy();
  44         }
  45         return p;
  46     }
  47 
  48     public boolean isAlive() {
  49         return p.isAlive();
  50     }
  51 
  52     public void run() {
  53         try {
  54             String line;
  55             BufferedReader is =
  56                 new BufferedReader(new InputStreamReader(p.getInputStream()));
  57             while ((line = is.readLine()) != null)
  58                 System.err.println("ProcessTrap: " + line);
  59         } catch(IOException e) {
  60             if (!e.getMessage().matches("[Ss]tream [Cc]losed")) {
  61                 throw new RuntimeException(e);
  62             }
  63         }
  64     }
  65 
  66     public abstract void runTest() throws Exception;
  67 }
  68 
  69 class UnixTest extends ProcessTest {
  70     public UnixTest(File script) throws IOException {
  71         script.deleteOnExit();
  72         createScript(script);
  73         bldr = new ProcessBuilder(script.getCanonicalPath());
  74         bldr.redirectErrorStream(true);
  75         bldr.directory(new File("."));
  76         p = bldr.start();
  77     }
  78 
  79     void createScript(File processTrapScript) throws IOException {
  80         processTrapScript.deleteOnExit();
  81         FileWriter fstream = new FileWriter(processTrapScript);
  82         try (BufferedWriter out = new BufferedWriter(fstream)) {
  83             out.write("#!/bin/bash\n" +
  84                 "echo \\\"ProcessTrap.sh started: trapping SIGTERM/SIGINT\\\"\n" +
  85                 "trap bashtrap SIGTERM SIGINT\n" +
  86                 "bashtrap()\n" +
  87                 "{\n" +
  88                 "    echo \\\"SIGTERM/SIGINT detected!\\\"\n" +
  89                 "}\n" +
  90                 "\n" +
  91                 "while :\n" +
  92                 "do\n" +
  93                 "    sleep 1;\n" +
  94                 "done\n");
  95         }
  96         processTrapScript.setExecutable(true, true);
  97     }
  98 
  99     @Override
 100     public void runTest() throws Exception {
 101         killProc(false);
 102         Thread.sleep(1000);
 103         if (!p.isAlive())
 104             throw new RuntimeException("Process terminated prematurely.");
 105         killProc(true).waitFor();
 106         if (p.isAlive())
 107             throw new RuntimeException("Problem terminating the process.");
 108     }
 109 }
 110 
 111 class MacTest extends UnixTest {
 112     public MacTest(File script) throws IOException {
 113         super(script);
 114     }
 115 
 116     @Override
 117     public void runTest() throws Exception {
 118         // On Mac, it appears that when we close the processes streams
 119         // after a destroy() call, the process terminates with a
 120         // SIGPIPE even if it was trapping the SIGTERM, so as with
 121         // windows, we skip the trap test and go straight to destroyForcibly().
 122         killProc(true).waitFor();
 123         if (p.isAlive())
 124             throw new RuntimeException("Problem terminating the process.");
 125     }
 126 }
 127 
 128 class WindowsTest extends ProcessTest {
 129     public WindowsTest() throws IOException {
 130         bldr = new ProcessBuilder("ftp");
 131         bldr.redirectErrorStream(true);
 132         bldr.directory(new File("."));
 133         p = bldr.start();
 134     }
 135 
 136     @Override
 137     public void runTest() throws Exception {
 138         killProc(true).waitFor();
 139     }
 140 }
 141 
 142 public class DestroyTest {
 143 
 144     public static ProcessTest getTest() throws Exception {
 145         String osName = System.getProperty("os.name");
 146         if (osName.startsWith("Windows")) {
 147             return new WindowsTest();
 148         } else if (osName.startsWith("Linux") == true) {
 149             return new UnixTest(
 150                 File.createTempFile("ProcessTrap-", ".sh",null));
 151         } else if (osName.startsWith("Mac OS")) {
 152             return new MacTest(
 153                 File.createTempFile("ProcessTrap-", ".sh",null));
 154         } else if (osName.equals("SunOS")) {
 155             return new UnixTest(
 156                 File.createTempFile("ProcessTrap-", ".sh",null));
 157         }
 158         return null;
 159     }
 160 
 161     public static void main(String args[]) throws Exception {
 162         ProcessTest test = getTest();
 163         if (test == null) {
 164             throw new RuntimeException("Unrecognised OS");
 165         } else {
 166             new Thread(test).start();
 167             Thread.sleep(1000);
 168             test.runTest();
 169         }
 170     }
 171 }
 172