Home | History | Annotate | Download | only in art
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package art;
     18 
     19 import java.util.concurrent.Semaphore;
     20 import java.util.Objects;
     21 
     22 public class Test1934 {
     23   private final static boolean isDalvik = System.getProperty("java.vm.name").equals("Dalvik");
     24 
     25   public static final boolean PRINT_STACK_TRACE = false;
     26 
     27   public static void run() throws Exception {
     28     System.out.println("Interrupt before start");
     29     testInterruptBeforeStart();
     30 
     31     System.out.println("Stop before start");
     32     testStopBeforeStart();
     33 
     34     System.out.println("Interrupt recur");
     35     testInterruptRecur();
     36 
     37     System.out.println("Stop Recur");
     38     testStopRecur();
     39 
     40     System.out.println("Interrupt spinning");
     41     testInterruptSpinning();
     42 
     43     System.out.println("Stop spinning");
     44     testStopSpinning();
     45 
     46     System.out.println("Interrupt wait");
     47     testInterruptWait();
     48 
     49     System.out.println("Stop wait");
     50     testStopWait();
     51 
     52     System.out.println("Stop in native");
     53     testStopInNative();
     54   }
     55 
     56   public static void testStopBeforeStart() throws Exception {
     57     final Throwable[] out_err = new Throwable[] { null, };
     58     final Object tst = new Object();
     59     Thread target = new Thread(() -> { while (true) { } }, "waiting thread!");
     60     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
     61     System.out.println("stopping other thread before starting");
     62     try {
     63       Threads.stopThread(target, new Error("AWESOME"));
     64       target.start();
     65       target.join();
     66       System.out.println("Other thread Stopped by: " + out_err[0]);
     67       if (PRINT_STACK_TRACE && out_err[0] != null) {
     68         out_err[0].printStackTrace();
     69       }
     70     } catch (Exception e) {
     71       System.out.println("Caught exception " + e);
     72     }
     73   }
     74 
     75   public static void testInterruptBeforeStart() throws Exception {
     76     final Throwable[] out_err = new Throwable[] { null, };
     77     final Object tst = new Object();
     78     Thread target = new Thread(() -> { while (true) { } }, "waiting thread!");
     79     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
     80     System.out.println("interrupting other thread before starting");
     81     try {
     82       Threads.interruptThread(target);
     83       target.start();
     84       target.join();
     85       System.out.println("Other thread interrupted. err: " + out_err[0]);
     86       if (PRINT_STACK_TRACE && out_err[0] != null) {
     87         out_err[0].printStackTrace();
     88       }
     89     } catch (Exception e) {
     90       System.out.println("Caught exception " + e);
     91     }
     92   }
     93 
     94   public static void testStopWait() throws Exception {
     95     final Throwable[] out_err = new Throwable[] { null, };
     96     final Object tst = new Object();
     97     final Semaphore sem = new Semaphore(0);
     98     Thread target = new Thread(() -> {
     99       sem.release();
    100       while (true) {
    101         try {
    102           synchronized (tst) {
    103             tst.wait();
    104           }
    105         } catch (InterruptedException e) { throw new Error("Interrupted!", e); }
    106       }
    107     }, "waiting thread!");
    108     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    109     target.start();
    110     sem.acquire();
    111     while (!Objects.equals(Monitors.getCurrentContendedMonitor(target), tst)) {}
    112     System.out.println("stopping other thread waiting");
    113     Threads.stopThread(target, new Error("AWESOME"));
    114     target.join();
    115     System.out.println("Other thread Stopped by: " + out_err[0]);
    116     if (PRINT_STACK_TRACE && out_err[0] != null) {
    117       out_err[0].printStackTrace();
    118     }
    119   }
    120 
    121   public static void testInterruptWait() throws Exception {
    122     final Throwable[] out_err = new Throwable[] { null, };
    123     final Object tst = new Object();
    124     final Semaphore sem = new Semaphore(0);
    125     Thread target = new Thread(() -> {
    126       sem.release();
    127       while (true) {
    128         try {
    129           synchronized (tst) {
    130             tst.wait();
    131           }
    132         } catch (InterruptedException e) { throw new Error("Interrupted!", e); }
    133       }
    134     }, "waiting thread!");
    135     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    136     target.start();
    137     sem.acquire();
    138     while (!Objects.equals(Monitors.getCurrentContendedMonitor(target), tst)) {}
    139     System.out.println("interrupting other thread waiting");
    140     Threads.interruptThread(target);
    141     target.join();
    142     System.out.println("Other thread interrupted. err: " + out_err[0]);
    143     if (PRINT_STACK_TRACE && out_err[0] != null) {
    144       out_err[0].printStackTrace();
    145     }
    146   }
    147 
    148   public static void doNothing() {}
    149   public static native long allocNativeMonitor();
    150   public static native void nativeWaitForOtherThread(long id);
    151   public static native void nativeDoInterleaved(long id, Runnable op);
    152   public static native void destroyNativeMonitor(long id);
    153   public static void testStopInNative() throws Exception {
    154     final Throwable[] out_err = new Throwable[] { null, };
    155     final long native_monitor_id = allocNativeMonitor();
    156     final Semaphore sem = new Semaphore(0);
    157     Thread target = new Thread(() -> {
    158       sem.release();
    159       nativeWaitForOtherThread(native_monitor_id);
    160       // We need to make sure we do something that can get the exception to be actually noticed.
    161       doNothing();
    162     }, "native waiting thread!");
    163     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    164     target.start();
    165     sem.acquire();
    166     System.out.println("stopping other thread");
    167     nativeDoInterleaved(
    168         native_monitor_id,
    169         () -> { Threads.stopThread(target, new Error("AWESOME")); });
    170     target.join();
    171 
    172     String out_err_msg;
    173     if (isDalvik || out_err[0] != null) {
    174       out_err_msg = out_err[0].toString();
    175     } else {
    176       // JVM appears to have a flaky bug with the native monitor wait,
    177       // causing exception not to be handled about 10% of the time.
    178       out_err_msg = "java.lang.Error: AWESOME";
    179     }
    180     System.out.println("Other thread Stopped by: " + out_err_msg);
    181     if (PRINT_STACK_TRACE && out_err[0] != null) {
    182       out_err[0].printStackTrace();
    183     }
    184     destroyNativeMonitor(native_monitor_id);
    185   }
    186 
    187   public static void doRecurCnt(Runnable r, int cnt) {
    188     if (r != null) {
    189       r.run();
    190     }
    191     if (cnt != 0) {
    192       doRecurCnt(r, cnt - 1);
    193     }
    194   }
    195 
    196   public static void testStopRecur() throws Exception {
    197     final Throwable[] out_err = new Throwable[] { null, };
    198     final Semaphore sem = new Semaphore(0);
    199     Thread target = new Thread(() -> {
    200       sem.release();
    201       while (true) {
    202         doRecurCnt(null, 50);
    203       }
    204     }, "recuring thread!");
    205     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    206     target.start();
    207     sem.acquire();
    208     System.out.println("stopping other thread recurring");
    209     Threads.stopThread(target, new Error("AWESOME!"));
    210     target.join();
    211     System.out.println("Other thread Stopped by: " + out_err[0]);
    212     if (PRINT_STACK_TRACE && out_err[0] != null) {
    213       out_err[0].printStackTrace();
    214     }
    215   }
    216 
    217   public static void testInterruptRecur() throws Exception {
    218     final Throwable[] out_err = new Throwable[] { null, };
    219     final Semaphore sem = new Semaphore(0);
    220     Thread target = new Thread(() -> {
    221       sem.release();
    222       while (true) {
    223         doRecurCnt(() -> {
    224           if (Thread.currentThread().isInterrupted()) { throw new Error("Interrupted!"); }
    225         }, 50);
    226       }
    227     }, "recuring thread!");
    228     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    229     target.start();
    230     sem.acquire();
    231     System.out.println("Interrupting other thread recurring");
    232     Threads.interruptThread(target);
    233     target.join();
    234     System.out.println("Other thread Interrupted. err: " + out_err[0]);
    235     if (PRINT_STACK_TRACE && out_err[0] != null) {
    236       out_err[0].printStackTrace();
    237     }
    238   }
    239 
    240   public static void testStopSpinning() throws Exception {
    241     final Throwable[] out_err = new Throwable[] { null, };
    242     final Semaphore sem = new Semaphore(0);
    243     Thread target = new Thread(() -> { sem.release(); while (true) {} }, "Spinning thread!");
    244     target.setUncaughtExceptionHandler((t, e) -> { out_err[0] = e; });
    245     target.start();
    246     sem.acquire();
    247     System.out.println("stopping other thread spinning");
    248     Threads.stopThread(target, new Error("AWESOME!"));
    249     target.join();
    250     System.out.println("Other thread Stopped by: " + out_err[0]);
    251     if (PRINT_STACK_TRACE && out_err[0] != null) {
    252       out_err[0].printStackTrace();
    253     }
    254   }
    255 
    256   public static void testInterruptSpinning() throws Exception {
    257     final Semaphore sem = new Semaphore(0);
    258     Thread target = new Thread(() -> {
    259       sem.release();
    260       while (!Thread.currentThread().isInterrupted()) { }
    261     }, "Spinning thread!");
    262     target.start();
    263     sem.acquire();
    264     System.out.println("Interrupting other thread spinning");
    265     Threads.interruptThread(target);
    266     target.join();
    267     System.out.println("Other thread Interrupted.");
    268   }
    269 }
    270