1 /*
   2  * Copyright (c) 2005, 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     4519200
  27  * @summary Confirm a Thread.stop before start complies with the spec
  28  * @author  Pete Soper
  29  *
  30  * Confirm that a thread that had its stop method invoked before start
  31  * does properly terminate with expected exception behavior. NOTE that
  32  * arbitrary application threads could return from their run methods faster
  33  * than the VM can throw an async exception.
  34  */
  35 public class StopBeforeStart {
  36 
  37     private static final int JOIN_TIMEOUT=10000;
  38 
  39     private class MyThrowable extends Throwable {
  40     }
  41 
  42     private class Catcher implements Thread.UncaughtExceptionHandler {
  43         private boolean nullaryStop;
  44         private Throwable theThrowable;
  45         private Throwable expectedThrowable;
  46         private boolean exceptionThrown;
  47 
  48         Catcher(boolean nullaryStop) {
  49             this.nullaryStop = nullaryStop;
  50             if (!nullaryStop) {
  51                 expectedThrowable = new MyThrowable();
  52             }
  53         }
  54 
  55         public void uncaughtException(Thread t, Throwable th) {
  56             exceptionThrown = true;
  57             theThrowable = th;
  58         }
  59 
  60         void check(String label) throws Throwable {
  61             if (!exceptionThrown) {
  62                 throw new RuntimeException(label +
  63                         " test:" + " missing uncaught exception");
  64             }
  65 
  66             if (nullaryStop) {
  67                 if (! (theThrowable instanceof ThreadDeath)) {
  68                     throw new RuntimeException(label +
  69                         " test:" + " expected ThreadDeath in uncaught handler");
  70                 }
  71             } else if (theThrowable != expectedThrowable) {
  72                 throw new RuntimeException(label +
  73                         " test:" + " wrong Throwable in uncaught handler");
  74             }
  75         }
  76     }
  77 
  78     private class MyRunnable implements Runnable {
  79         public void run() {
  80             while(true)
  81                 ;
  82         }
  83     }
  84 
  85     private class MyThread extends Thread {
  86         public void run() {
  87             while(true)
  88                 ;
  89         }
  90     }
  91 
  92 
  93     public static void main(String args[]) throws Throwable {
  94         (new StopBeforeStart()).doit();
  95         System.out.println("Test passed");
  96     }
  97 
  98     private void doit() throws Throwable {
  99 
 100         runit(false, new Thread(new MyRunnable()),"Thread");
 101         runit(true, new Thread(new MyRunnable()),"Thread");
 102         runit(false, new MyThread(),"Runnable");
 103         runit(true, new MyThread(),"Runnable");
 104     }
 105 
 106     private void runit(boolean nullaryStop, Thread thread,
 107                         String type) throws Throwable {
 108 
 109         Catcher c = new Catcher(nullaryStop);
 110         thread.setUncaughtExceptionHandler(c);
 111 
 112         if (nullaryStop) {
 113             thread.stop();
 114         } else {
 115             thread.stop(c.expectedThrowable);
 116         }
 117 
 118         thread.start();
 119         thread.join(JOIN_TIMEOUT);
 120 
 121         if (thread.getState() != Thread.State.TERMINATED) {
 122 
 123             thread.stop();
 124 
 125             // Under high load this could be a false positive
 126             throw new RuntimeException(type +
 127                         " test:" + " app thread did not terminate");
 128         }
 129 
 130         c.check(type);
 131     }
 132 }