1 /* 2 * Copyright (c) 2013, 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 /* @test 25 * @bug 8024833 26 * @summary Tests interruption of threads mapping sections of a file channel in 27 * an attempt to deadlock due to nesting of begin calls. 28 */ 29 import java.io.IOException; 30 import java.nio.ByteBuffer; 31 import java.nio.channels.*; 32 import java.nio.channels.FileChannel.MapMode; 33 import java.nio.file.*; 34 import java.util.concurrent.Semaphore; 35 import static java.nio.file.StandardOpenOption.*; 36 37 public class InterruptMapDeadlock { 38 39 static class Mapper extends Thread { 40 final FileChannel fc; 41 final Semaphore gate; 42 volatile Exception exception; 43 Mapper(FileChannel fc, Semaphore gate)44 Mapper(FileChannel fc, Semaphore gate) { 45 this.fc = fc; 46 this.gate = gate; 47 } 48 49 @Override run()50 public void run() { 51 try { 52 gate.acquireUninterruptibly(); 53 fc.map(MapMode.READ_ONLY, 0, 1); 54 throw new Exception("Map succeeded"); 55 } catch (IOException x) { 56 System.out.println(x.getClass() + " (expected)"); 57 } catch (Exception unexpected) { 58 this.exception = unexpected; 59 } 60 } 61 exception()62 Exception exception() { 63 return exception; 64 } 65 startMapper(FileChannel fc, Semaphore gate)66 static Mapper startMapper(FileChannel fc, Semaphore gate) { 67 Mapper r = new Mapper(fc, gate); 68 r.setDaemon(true); 69 r.start(); 70 return r; 71 } 72 } 73 74 static class Interruptor extends Thread { 75 76 final Mapper[] mappers; 77 final Semaphore gate; 78 Interruptor(Mapper[] mappers, Semaphore gate)79 Interruptor(Mapper[] mappers, Semaphore gate) { 80 this.mappers = mappers; 81 this.gate = gate; 82 } 83 run()84 public void run() { 85 gate.release(mappers.length); 86 for (Mapper m : mappers) { 87 m.interrupt(); 88 } 89 } 90 } 91 // the number of mapper threads to start 92 private static final int MAPPER_COUNT = 4; 93 main(String[] args)94 public static void main(String[] args) throws Exception { 95 Path file = Paths.get("data.txt"); 96 FileChannel.open(file, CREATE, TRUNCATE_EXISTING, WRITE).close(); 97 98 Mapper[] mappers = new Mapper[MAPPER_COUNT]; 99 100 for (int i=1; i<=20; i++) { 101 System.out.format("Iteration: %s%n", i); 102 103 FileChannel fc = FileChannel.open(file); 104 boolean failed = false; 105 106 Semaphore gate = new Semaphore(0); 107 // start mapper threads 108 for (int j=0; j<MAPPER_COUNT; j++) { 109 mappers[j] = Mapper.startMapper(fc, gate); 110 } 111 112 // interrupt and wait for the mappers to terminate 113 Interruptor interruptor = new Interruptor(mappers, gate); 114 interruptor.start(); 115 try { 116 interruptor.join(10000); 117 if (interruptor.isAlive()) { 118 System.err.println("Interruptor thread did not terminate:"); 119 Throwable t = new Exception("Stack trace"); 120 t.setStackTrace(interruptor.getStackTrace()); 121 t.printStackTrace(); 122 failed = true; 123 } 124 } catch (InterruptedException x) { 125 System.err.println("Main thread was interrupted"); 126 failed = true; 127 } 128 129 for (Mapper m: mappers) { 130 try { 131 m.join(10000); 132 Exception e = m.exception(); 133 if (e != null) { 134 System.err.println("Mapper thread failed with: " + e); 135 failed = true; 136 } else if (m.isAlive()) { 137 System.err.println("Mapper thread did not terminate:"); 138 Throwable t = new Exception("Stack trace"); 139 t.setStackTrace(m.getStackTrace()); 140 t.printStackTrace(); 141 failed = true; 142 } 143 } catch (InterruptedException x) { 144 System.err.println("Main thread was interrupted"); 145 failed = true; 146 } 147 } 148 149 if (failed) 150 throw new RuntimeException("Test failed - see log for details"); 151 else 152 fc.close(); 153 } 154 } 155 } 156