Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8011537

(fs) Path.register(..) clears interrupt status of thread with no InterruptedException

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 9
    • 7
    • core-libs
    • None
    • b13

        FULL PRODUCT VERSION :
        java version " 1.7.0_11 "
        Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
        Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :
        A thread after interrupted, calls path.register(http://docs.oracle.com/javase/7/docs/api/java/nio/file/Path.html#register%28java.nio.file.WatchService,%20java.nio.file.WatchEvent.Kind...%29) method. The interrupt status gets cleared without any InterruptedException being thrown. Resulting in unsuccessful termination of a task in ExecutorService.

        The documentation doesn't explain any behavior for this.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Execute the code. You will probably have to try different sleep times to replicate it (at line c). On my computer sleep time of 10 ms replicates the case 99/100 times.



        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        interrupted //line 1
        Interrupt Status: true at line a //line 2
        Interrupt Status: true at line b. //line 3

        /*
        if line 1 is printed. Then line 2 and line 3 should print true. Which means that the thread was interrupted. In reality, it prints false which means the status is cleared without any exception being thrown.
        */
        ACTUAL -
        interrupted
        Interrupt Status: true at line a
        Interrupt Status: false at line b.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.io.*;
        import java.nio.file.*;
        import static java.nio.file.LinkOption.*;
        import static java.nio.file.StandardWatchEventKinds.*;
        import java.nio.file.attribute.*;
        import java.util.*;
        import java.util.logging.Level;
        import java.util.logging.Logger;

        /**
        * Example to watch a directory (or tree) for changes to files.
        */

        public class WatchDir {

        private final WatchService watcher;
        private final Map<WatchKey,Path> keys;
        private final boolean recursive;



        /**
         * Register the given directory with the WatchService
         */
        private void register(Path dir) throws IOException {
            System.out.format( " Interrupt Status: " +Thread.currentThread().isInterrupted()+ " at line a
         " , dir);//line a
            WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
             System.out.format( " Interrupt Status: " +Thread.currentThread().isInterrupted()+ " at line b.
         " , dir);//line b
            Path prev = keys.get(key);

            keys.put(key, dir);
        }

        /**
         * Register the given directory, and all its sub-directories, with the
         * WatchService.
         */
        private void registerAll(final Path start) throws IOException {
            // register directory and sub-directories
            Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                    throws IOException {
                    //System.out.format(Thread.currentThread().isInterrupted()+ " register: %s
         " , dir);
                    register(dir);
                    return FileVisitResult.CONTINUE;
                }
            });

        }

        /**
         * Creates a WatchService and registers the given directory
         */
        WatchDir(Path dir, boolean recursive) throws IOException {
            this.watcher = FileSystems.getDefault().newWatchService();
            this.keys = new HashMap<WatchKey,Path>();
            this.recursive = recursive;
            //System.out.format( " Scanning %s ... " +Thread.currentThread().isInterrupted()+ "
          " , dir);
                registerAll(dir);
        }

        /**
         * Process all events for keys queued to the watcher
         */



        public static void main(String[] args) throws Exception {

            // register directory and process its events
            File f = new File( " test_interrupt_status " );
        f.mkdir();
        Path dir = new File( " ./test_interrupt_status " ).toPath();
            final Thread g = Thread.currentThread();
            new Thread(new Runnable(){

                public void run() {
                    try {
                        Thread.currentThread().sleep(10);//keep changing values here. line c
                        System.out.println( " interrupted " );
                        g.interrupt();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(WatchDir.class.getName()).log(Level.SEVERE, null, ex);
                    }

                }

            }).start();
            //System.out.println(Thread.currentThread().isInterrupted());
            new WatchDir(dir, true);
        }
        }
        ---------- END SOURCE ----------

        SUPPORT :
        YES

              igerasim Ivan Gerasimov
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

                Created:
                Updated:
                Resolved: