jdk/test/java/nio/channels/FileChannel/InterruptMapDeadlock.java
changeset 21318 2dffe829fb18
child 37817 5fd92fde53db
equal deleted inserted replaced
21317:176090ca2be7 21318:2dffe829fb18
       
     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 
       
    44         Mapper(FileChannel fc, Semaphore gate) {
       
    45             this.fc = fc;
       
    46             this.gate = gate;
       
    47         }
       
    48 
       
    49         @Override
       
    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 
       
    62         Exception exception() {
       
    63             return exception;
       
    64         }
       
    65 
       
    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 
       
    79         Interruptor(Mapper[] mappers, Semaphore gate) {
       
    80             this.mappers = mappers;
       
    81             this.gate = gate;
       
    82         }
       
    83 
       
    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 
       
    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 }