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

Heavy load in WatchService leads to deadlock

    Details

    • Subcomponent:
    • CPU:
      x86
    • OS:
      other

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_31"
      Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      OS X 10.10.2 (14C109)

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Filesystem: "Journaled HFS+" or "jhfs+" - Mac OS Extended (Journaled)

      A DESCRIPTION OF THE PROBLEM :
      A directory is watched recursively using java.nio.file.WatchService and the code provided at "http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java". If a hierarchy of directories is repeatedly renamed a top levels a deadlock can be observed.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1) Run the WatchDir example at "http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java" with recursion enabled to any directory.

      2) Copy the provided python script (see bottom of this textfield) in the initially watched directory and execute it from there. It creates a folder hierarchy with a depth of 100 subfolders and alternatively renames directories at level 0 and level 1.

      3) After several iterations a deadlock occurs at "sun.nio.fs.PollingWatchService$PollingWatchKey.cancel(PollingWatchService.java:308)" and "sun.nio.fs.PollingWatchService$PollingWatchKey.disable(PollingWatchService.java:299)". Further information can be found in the provided thread dump.

      PYTHON SCRIPT:

      import os
      import shutil
      import time

      def toPath( pathElements ):
          "convert path elements to path string"
          
          path = "";
          for element in pathElements:
              path += element + "/"
          return path

      def cleanCurrentDir():
          "remove every dir"
          for content in os.listdir(os.getcwd()):
              if( os.path.isdir(content) ):
                  shutil.rmtree(content)

      # clean up
      cleanCurrentDir()

      # define depth of hierachie
      depth = 100;
      dirPrefix = "dir_"

      # construct list of path elements
      pathElements=[]
      for i in range(depth):
          pathElements.append("dir")

      #rename first to path elements
      pathElements[0] = dirPrefix + "0";
      pathElements[1] = dirPrefix + "0";

      # convert to path
      entirePath = toPath(pathElements)

      # create hierachie
      os.makedirs(entirePath)

      NIterations = 1000
      sleepTime = 1.5 # in seconds

      for i in range(NIterations):
          
          # rename dirs
          newName = dirPrefix + str(i+1);
          if( i % 2 == 0):
              
              #raw_input("Name of directory changing at level 0. Press enter to continue...")
              
              os.rename(pathElements[0], newName)
              pathElements[0] = newName
              
              # simulate delay
              time.sleep(sleepTime)

          else:
              #raw_input("Name of directory changing at level 1. Press enter to continue...")
              
              os.chdir(pathElements[0])
              os.rename(pathElements[1], newName)
              pathElements[1] = newName
              os.chdir("..")
              
              # simulate delay
              time.sleep(2*sleepTime)
              
          print "current paths " + toPath(pathElements[:3]) + "..."



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected results would be watched directories without deadlock.
      ACTUAL -
      The actual result is a deadlock, which leads to non watched directories.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :

      2015-03-03 14:20:01
      Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode):

      "RMI TCP Connection(2)-192.168.123.180" #16 daemon prio=9 os_prio=31 tid=0x00007fa0d4814800 nid=0x5c03 runnable [0x000000011ee4a000]
         java.lang.Thread.State: RUNNABLE
      at java.net.SocketInputStream.socketRead0(Native Method)
      at java.net.SocketInputStream.read(SocketInputStream.java:150)
      at java.net.SocketInputStream.read(SocketInputStream.java:121)
      at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
      at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
      - locked <0x0000000795fead68> (a java.io.BufferedInputStream)
      at java.io.FilterInputStream.read(FilterInputStream.java:83)
      at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$240(TCPTransport.java:683)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/398973873.run(Unknown Source)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - <0x0000000795c05f18> (a java.util.concurrent.ThreadPoolExecutor$Worker)

      "JMX server connection timeout 15" #15 daemon prio=9 os_prio=31 tid=0x00007fa0d40d2800 nid=0x5a03 in Object.wait() [0x000000011ec73000]
         java.lang.Thread.State: TIMED_WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:168)
      - locked <0x0000000795d9da50> (a [I)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - None

      "RMI Scheduler(0)" #14 daemon prio=9 os_prio=31 tid=0x00007fa0d399a800 nid=0x5803 waiting on condition [0x000000011eb70000]
         java.lang.Thread.State: TIMED_WAITING (parking)
      at sun.misc.Unsafe.park(Native Method)
      - parking to wait for <0x0000000795b5add8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
      at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
      at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
      at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
      at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
      at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - None

      "RMI TCP Connection(1)-192.168.123.180" #13 daemon prio=9 os_prio=31 tid=0x00007fa0d40b0800 nid=0x5603 runnable [0x000000011ea6c000]
         java.lang.Thread.State: RUNNABLE
      at java.net.SocketInputStream.socketRead0(Native Method)
      at java.net.SocketInputStream.read(SocketInputStream.java:150)
      at java.net.SocketInputStream.read(SocketInputStream.java:121)
      at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
      at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
      - locked <0x0000000795d6ff50> (a java.io.BufferedInputStream)
      at java.io.FilterInputStream.read(FilterInputStream.java:83)
      at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:550)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$240(TCPTransport.java:683)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1/398973873.run(Unknown Source)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - <0x0000000795c05058> (a java.util.concurrent.ThreadPoolExecutor$Worker)

      "RMI TCP Accept-0" #12 daemon prio=9 os_prio=31 tid=0x00007fa0d40a7800 nid=0x5507 runnable [0x000000011e96a000]
         java.lang.Thread.State: RUNNABLE
      at java.net.PlainSocketImpl.socketAccept(Native Method)
      at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
      at java.net.ServerSocket.implAccept(ServerSocket.java:545)
      at java.net.ServerSocket.accept(ServerSocket.java:513)
      at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
      at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:400)
      at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:372)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - None

      "Attach Listener" #10 daemon prio=9 os_prio=31 tid=0x00007fa0d483b000 nid=0x4d03 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "Thread-0" #9 daemon prio=5 os_prio=31 tid=0x00007fa0d4059800 nid=0x4b03 waiting for monitor entry [0x000000011e753000]
         java.lang.Thread.State: BLOCKED (on object monitor)
      at sun.nio.fs.PollingWatchService$PollingWatchKey.cancel(PollingWatchService.java:308)
      - waiting to lock <0x00000007957c0a80> (a java.util.HashMap)
      at sun.nio.fs.PollingWatchService$PollingWatchKey.poll(PollingWatchService.java:331)
      - locked <0x00000007958970f0> (a sun.nio.fs.PollingWatchService$PollingWatchKey)
      at sun.nio.fs.PollingWatchService$PollingWatchKey$1.run(PollingWatchService.java:290)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)

         Locked ownable synchronizers:
      - <0x000000079582bf38> (a java.util.concurrent.ThreadPoolExecutor$Worker)

      "Service Thread" #8 daemon prio=9 os_prio=31 tid=0x00007fa0d4044000 nid=0x4703 runnable [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "C1 CompilerThread2" #7 daemon prio=9 os_prio=31 tid=0x00007fa0d383f000 nid=0x4503 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "C2 CompilerThread1" #6 daemon prio=9 os_prio=31 tid=0x00007fa0d383c800 nid=0x4303 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "C2 CompilerThread0" #5 daemon prio=9 os_prio=31 tid=0x00007fa0d5017000 nid=0x4103 waiting on condition [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007fa0d5000000 nid=0x3013 runnable [0x0000000000000000]
         java.lang.Thread.State: RUNNABLE

         Locked ownable synchronizers:
      - None

      "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007fa0d4027000 nid=0x2d03 in Object.wait() [0x000000011c721000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x00000007955862f8> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142)
      - locked <0x00000007955862f8> (a java.lang.ref.ReferenceQueue$Lock)
      at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:158)
      at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

         Locked ownable synchronizers:
      - None

      "Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007fa0d4808800 nid=0x2b03 in Object.wait() [0x000000011c61e000]
         java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on <0x0000000795585d68> (a java.lang.ref.Reference$Lock)
      at java.lang.Object.wait(Object.java:502)
      at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:157)
      - locked <0x0000000795585d68> (a java.lang.ref.Reference$Lock)

         Locked ownable synchronizers:
      - None

      "main" #1 prio=5 os_prio=31 tid=0x00007fa0d4008000 nid=0x1303 waiting for monitor entry [0x0000000104f26000]
         java.lang.Thread.State: BLOCKED (on object monitor)
      at sun.nio.fs.PollingWatchService$PollingWatchKey.disable(PollingWatchService.java:299)
      - waiting to lock <0x00000007958970f0> (a sun.nio.fs.PollingWatchService$PollingWatchKey)
      at sun.nio.fs.PollingWatchService.doPrivilegedRegister(PollingWatchService.java:171)
      - locked <0x00000007957c0a80> (a java.util.HashMap)
      - locked <0x00000007957c0a70> (a java.lang.Object)
      at sun.nio.fs.PollingWatchService.access$000(PollingWatchService.java:45)
      at sun.nio.fs.PollingWatchService$2.run(PollingWatchService.java:130)
      at sun.nio.fs.PollingWatchService$2.run(PollingWatchService.java:127)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.nio.fs.PollingWatchService.register(PollingWatchService.java:126)
      at sun.nio.fs.UnixPath.register(UnixPath.java:897)
      at sun.nio.fs.AbstractPath.register(AbstractPath.java:104)
      at com.watchdir.test.WatchDir.register(WatchDir.java:61)
      at com.watchdir.test.WatchDir.access$0(WatchDir.java:60)
      at com.watchdir.test.WatchDir$1.preVisitDirectory(WatchDir.java:86)
      at com.watchdir.test.WatchDir$1.preVisitDirectory(WatchDir.java:1)
      at java.nio.file.Files.walkFileTree(Files.java:2677)
      at java.nio.file.Files.walkFileTree(Files.java:2742)
      at com.watchdir.test.WatchDir.registerAll(WatchDir.java:81)
      at com.watchdir.test.WatchDir.processEvents(WatchDir.java:153)
      at com.watchdir.test.WatchDir.main(WatchDir.java:194)

         Locked ownable synchronizers:
      - None

      "VM Thread" os_prio=31 tid=0x00007fa0d4801000 nid=0x2903 runnable

      "GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007fa0d380f800 nid=0x2103 runnable

      "GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007fa0d3810000 nid=0x2303 runnable

      "GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007fa0d3810800 nid=0x2503 runnable

      "GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007fa0d3811800 nid=0x2703 runnable

      "VM Periodic Task Thread" os_prio=31 tid=0x00007fa0d402a800 nid=0x4903 waiting on condition

      JNI global references: 289


      Found one Java-level deadlock:
      =============================
      "Thread-0":
        waiting to lock monitor 0x00007fa0d5010288 (object 0x00000007957c0a80, a java.util.HashMap),
        which is held by "main"
      "main":
        waiting to lock monitor 0x00007fa0d500ef48 (object 0x00000007958970f0, a sun.nio.fs.PollingWatchService$PollingWatchKey),
        which is held by "Thread-0"

      Java stack information for the threads listed above:
      ===================================================
      "Thread-0":
      at sun.nio.fs.PollingWatchService$PollingWatchKey.cancel(PollingWatchService.java:308)
      - waiting to lock <0x00000007957c0a80> (a java.util.HashMap)
      at sun.nio.fs.PollingWatchService$PollingWatchKey.poll(PollingWatchService.java:331)
      - locked <0x00000007958970f0> (a sun.nio.fs.PollingWatchService$PollingWatchKey)
      at sun.nio.fs.PollingWatchService$PollingWatchKey$1.run(PollingWatchService.java:290)
      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
      at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
      "main":
      at sun.nio.fs.PollingWatchService$PollingWatchKey.disable(PollingWatchService.java:299)
      - waiting to lock <0x00000007958970f0> (a sun.nio.fs.PollingWatchService$PollingWatchKey)
      at sun.nio.fs.PollingWatchService.doPrivilegedRegister(PollingWatchService.java:171)
      - locked <0x00000007957c0a80> (a java.util.HashMap)
      - locked <0x00000007957c0a70> (a java.lang.Object)
      at sun.nio.fs.PollingWatchService.access$000(PollingWatchService.java:45)
      at sun.nio.fs.PollingWatchService$2.run(PollingWatchService.java:130)
      at sun.nio.fs.PollingWatchService$2.run(PollingWatchService.java:127)
      at java.security.AccessController.doPrivileged(Native Method)
      at sun.nio.fs.PollingWatchService.register(PollingWatchService.java:126)
      at sun.nio.fs.UnixPath.register(UnixPath.java:897)
      at sun.nio.fs.AbstractPath.register(AbstractPath.java:104)
      at com.watchdir.test.WatchDir.register(WatchDir.java:61)
      at com.watchdir.test.WatchDir.access$0(WatchDir.java:60)
      at com.watchdir.test.WatchDir$1.preVisitDirectory(WatchDir.java:86)
      at com.watchdir.test.WatchDir$1.preVisitDirectory(WatchDir.java:1)
      at java.nio.file.Files.walkFileTree(Files.java:2677)
      at java.nio.file.Files.walkFileTree(Files.java:2742)
      at com.watchdir.test.WatchDir.registerAll(WatchDir.java:81)
      at com.watchdir.test.WatchDir.processEvents(WatchDir.java:153)
      at com.watchdir.test.WatchDir.main(WatchDir.java:194)

      Found 1 deadlock.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      This source code can also be found at "http://docs.oracle.com/javase/tutorial/essential/io/examples/WatchDir.java".

      /*
       * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       *
       * Redistribution and use in source and binary forms, with or without
       * modification, are permitted provided that the following conditions
       * are met:
       *
       * - Redistributions of source code must retain the above copyright
       * notice, this list of conditions and the following disclaimer.
       *
       * - Redistributions in binary form must reproduce the above copyright
       * notice, this list of conditions and the following disclaimer in the
       * documentation and/or other materials provided with the distribution.
       *
       * - Neither the name of Oracle nor the names of its
       * contributors may be used to endorse or promote products derived
       * from this software without specific prior written permission.
       *
       * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       */

      import java.nio.file.*;
      import static java.nio.file.StandardWatchEventKinds.*;
      import static java.nio.file.LinkOption.*;
      import java.nio.file.attribute.*;
      import java.io.*;
      import java.util.*;

      /**
       * 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;
          private boolean trace = false;

          @SuppressWarnings("unchecked")
          static <T> WatchEvent<T> cast(WatchEvent<?> event) {
              return (WatchEvent<T>)event;
          }

          /**
           * Register the given directory with the WatchService
           */
          private void register(Path dir) throws IOException {
              WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
              if (trace) {
                  Path prev = keys.get(key);
                  if (prev == null) {
                      System.out.format("register: %s\n", dir);
                  } else {
                      if (!dir.equals(prev)) {
                          System.out.format("update: %s -> %s\n", prev, dir);
                      }
                  }
              }
              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
                  {
                      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;

              if (recursive) {
                  System.out.format("Scanning %s ...\n", dir);
                  registerAll(dir);
                  System.out.println("Done.");
              } else {
                  register(dir);
              }

              // enable trace after initial registration
              this.trace = true;
          }

          /**
           * Process all events for keys queued to the watcher
           */
          void processEvents() {
              for (;;) {

                  // wait for key to be signalled
                  WatchKey key;
                  try {
                      key = watcher.take();
                  } catch (InterruptedException x) {
                      return;
                  }

                  Path dir = keys.get(key);
                  if (dir == null) {
                      System.err.println("WatchKey not recognized!!");
                      continue;
                  }

                  for (WatchEvent<?> event: key.pollEvents()) {
                      WatchEvent.Kind kind = event.kind();

                      // TBD - provide example of how OVERFLOW event is handled
                      if (kind == OVERFLOW) {
                          continue;
                      }

                      // Context for directory entry event is the file name of entry
                      WatchEvent<Path> ev = cast(event);
                      Path name = ev.context();
                      Path child = dir.resolve(name);

                      // print out event
                      System.out.format("%s: %s\n", event.kind().name(), child);

                      // if directory is created, and watching recursively, then
                      // register it and its sub-directories
                      if (recursive && (kind == ENTRY_CREATE)) {
                          try {
                              if (Files.isDirectory(child, NOFOLLOW_LINKS)) {
                                  registerAll(child);
                              }
                          } catch (IOException x) {
                              // ignore to keep sample readbale
                          }
                      }
                  }

                  // reset key and remove from set if directory no longer accessible
                  boolean valid = key.reset();
                  if (!valid) {
                      keys.remove(key);

                      // all directories are inaccessible
                      if (keys.isEmpty()) {
                          break;
                      }
                  }
              }
          }

          static void usage() {
              System.err.println("usage: java WatchDir [-r] dir");
              System.exit(-1);
          }

          public static void main(String[] args) throws IOException {
              // parse arguments
              if (args.length == 0 || args.length > 2)
                  usage();
              boolean recursive = false;
              int dirArg = 0;
              if (args[0].equals("-r")) {
                  if (args.length < 2)
                      usage();
                  recursive = true;
                  dirArg++;
              }

              // register directory and process its events
              Path dir = Paths.get(args[dirArg]);
              new WatchDir(dir, recursive).processEvents();
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      No workaround found yet.

        Activity

        Hide
        alanb Alan Bateman added a comment -
        This looks specific to the polling based WatchService, used on Solaris 10 and OSX.
        Show
        alanb Alan Bateman added a comment - This looks specific to the polling based WatchService, used on Solaris 10 and OSX.
        Hide
        bpb Brian Burkhalter added a comment -
        I ran the test given in the description using my local clone of JDK 9 on Mac OS 10.9.5 and the test ran to completion without a problem.
        Show
        bpb Brian Burkhalter added a comment - I ran the test given in the description using my local clone of JDK 9 on Mac OS 10.9.5 and the test ran to completion without a problem.

          People

          • Assignee:
            psonal Pallavi Sonal
            Reporter:
            webbuggrp Webbug Group
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: