From tigran.mkrtchyan at desy.de Wed Dec 1 03:31:44 2010 From: tigran.mkrtchyan at desy.de (Tigran Mkrtchyan) Date: Wed, 01 Dec 2010 12:31:44 +0100 Subject: sendfile is broken on solaris with -d64? In-Reply-To: <4CEFD521.4050109@oracle.com> References: <4CEFCD3C.1000506@desy.de> <4CEFD521.4050109@oracle.com> Message-ID: <4CF63220.5020404@desy.de> Hi Alan, do you have a ticket number? Thanks, Tigran. On 11/26/2010 04:41 PM, Alan Bateman wrote: > Tigran Mkrtchyan wrote: >> >> >> Dear NIO gurus, >> >> we observed some weird behavior with sendfile on a solaris box with >> 1.6.0_22 and 1.7.0 >> >> we notice, that with -d64 FileChannel.transferTo() method uses memory >> mapped file instead of >> using systems sendfile call. > Thanks for the bug report. The 64-bit libsendfile is in /lib/64 > whereas this code was originally written to only attempt to load it > from /usr/lib. Also with a 64-bit library the symbol is sendfilev64. > I'm kinda surprised it hasn't been noticed before. I'll create a bug > for this. > > -Alan From Alan.Bateman at oracle.com Wed Dec 1 03:34:14 2010 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Wed, 01 Dec 2010 11:34:14 +0000 Subject: sendfile is broken on solaris with -d64? In-Reply-To: <4CF63220.5020404@desy.de> References: <4CEFCD3C.1000506@desy.de> <4CEFD521.4050109@oracle.com> <4CF63220.5020404@desy.de> Message-ID: <4CF632B6.8090305@oracle.com> Tigran Mkrtchyan wrote: > Hi Alan, > > do you have a ticket number? > > Thanks, > Tigran. Here it is: http://bugs.sun.com/view_bug.do?bug_id=7002957 I'll try to get this fixed in jdk7 soon. -Alan. From tigran.mkrtchyan at desy.de Wed Dec 1 03:38:21 2010 From: tigran.mkrtchyan at desy.de (Tigran Mkrtchyan) Date: Wed, 01 Dec 2010 12:38:21 +0100 Subject: sendfile is broken on solaris with -d64? In-Reply-To: <4CF632B6.8090305@oracle.com> References: <4CEFCD3C.1000506@desy.de> <4CEFD521.4050109@oracle.com> <4CF63220.5020404@desy.de> <4CF632B6.8090305@oracle.com> Message-ID: <4CF633AD.4030109@desy.de> On 12/01/2010 12:34 PM, Alan Bateman wrote: > Tigran Mkrtchyan wrote: >> Hi Alan, >> >> do you have a ticket number? >> >> Thanks, >> Tigran. > Here it is: > > http://bugs.sun.com/view_bug.do?bug_id=7002957 > > I'll try to get this fixed in jdk7 soon. and what about jdk6 ? This is the current production version. Tigran. > > -Alan. > From chris.hegarty at oracle.com Tue Dec 7 10:00:17 2010 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Tue, 07 Dec 2010 18:00:17 +0000 Subject: 7003155: (fs) Paths.get() does not handle escaped octets correctly In-Reply-To: <4CF3D47A.1020207@oracle.com> References: <4CF3D47A.1020207@oracle.com> Message-ID: <4CFE7631.90308@oracle.com> Looks fine Alan, -Chris. On 11/29/10 04:27 PM, Alan Bateman wrote: > > The code for converting URIs to Paths in the Solaris/Linux file system > provider is not correct. It's using the decoded path component of the > URI (ie: de-quoted) and so must be converted from UTF-8. The webrev with > the change is here: > http://cr.openjdk.java.net/~alanb/7003155/webrev/ > > Thanks, > Alan. From xueming.shen at oracle.com Tue Dec 7 12:07:36 2010 From: xueming.shen at oracle.com (Xueming Shen) Date: Tue, 07 Dec 2010 12:07:36 -0800 Subject: 7003155: (fs) Paths.get() does not handle escaped octets correctly In-Reply-To: <4CF3D47A.1020207@oracle.com> References: <4CF3D47A.1020207@oracle.com> Message-ID: <4CFE9408.1060002@oracle.com> Alan, why UTF-8 is being used here? The default charset should be used to do the conversion between byte[] and String. It appears the toUri should also do a byte[] -> String (default charset) -> byte[] (utf-8) before escaping. -Sherman On 11/29/2010 08:27 AM, Alan Bateman wrote: > > The code for converting URIs to Paths in the Solaris/Linux file system > provider is not correct. It's using the decoded path component of the > URI (ie: de-quoted) and so must be converted from UTF-8. The webrev > with the change is here: > http://cr.openjdk.java.net/~alanb/7003155/webrev/ > > Thanks, > Alan. From wolfgang.baltes at laposte.net Wed Dec 15 15:19:00 2010 From: wolfgang.baltes at laposte.net (wolfgang.baltes) Date: Thu, 16 Dec 2010 00:19:00 +0100 (CET) Subject: WatchService Message-ID: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> Hi, I have started to use the WatchService and would like to get confirmation for some of my observations. At least one of them is not in agreement with the documentation. My system is Windows 7 Ultimate 64bit with JDK7-b121 32bit and using Eclipse 3.61 32bit as the development platform. I am writing a piece of code that watches one or several directories recursively or not for file additions and deletions. My observations are for a directory tree where all directories/subdirectories are being watched. I use Windows Explorer to copy files and directory trees into this directory tree and to delete them. 1 - If I delete a file at any level in the tree, then I get the ENTRY_DELETE event for the file and an ENTRY_MODIFIED event for its parent directory. - This should be normal. 2 - If I delete a subdirectory that contains files but no further subdirectories, then I receive an ENTRY_DELETE event for the subdirectory and an ENTRY_MODIFIED event for its parent directory. In addition - and only sometimes - I also receieve ENTRY_DELETE events for the files within the subdirectory. - I assume that this is normal, although I don't understand the random behavior of getting or not getting events regarding the files. 3 - If I try to delete a subdirectory tree - that is a subdirectory with nested directories - then Windows Explorer does not let me delete the tree. The WatchService seems to block this. I can however, delete this tree by starting at the bottom (leaf) directories and delete them one at a time. This corresponds essentially to the scenario described in 2. - This may be normal, but is certainly not convenient. Is this a Windows feature? 4 - Contrary to the documentation (tutorial on WatchService), the WatchKey remains valid (isValid()) after deletion of the associated directory. That is, the expression (dir.notExists() && key.isValid()), where key is the WatchKey associated with dir is true. The first part of the expression confirms that dir is deleted, and the second part should be false if the key is automatically cancelled. - I don' think this is normal at all! Thanks for any comments you may have, Wolfgang. Une messagerie gratuite, garantie ? vie et des services en plus, ?a vous tente ? Je cr?e ma bo?te mail www.laposte.net -------------- next part -------------- An HTML attachment was scrubbed... URL: http://mail.openjdk.java.net/pipermail/nio-dev/attachments/20101216/9346caee/attachment.html From Alan.Bateman at oracle.com Thu Dec 16 06:48:41 2010 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Thu, 16 Dec 2010 14:48:41 +0000 Subject: WatchService In-Reply-To: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> References: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> Message-ID: <4D0A26C9.5000105@oracle.com> wolfgang.baltes wrote: > > Hi, > > I have started to use the WatchService and would like to get > confirmation for some of my observations. At least one of them is not > in agreement with the documentation. > > My system is Windows 7 Ultimate 64bit with JDK7-b121 32bit and using > Eclipse 3.61 32bit as the development platform. I am writing a piece > of code that watches one or several directories recursively or not for > file additions and deletions. > > My observations are for a directory tree where all > directories/subdirectories are being watched. I use Windows Explorer > to copy files and directory trees into this directory tree and to > delete them. > > 1 - If I delete a file at any level in the tree, then I get the > ENTRY_DELETE event for the file and an ENTRY_MODIFIED event for its > parent directory. - This should be normal. > > 2 - If I delete a subdirectory that contains files but no further > subdirectories, then I receive an ENTRY_DELETE event for the > subdirectory and an ENTRY_MODIFIED event for its parent directory. In > addition - and only sometimes - I also receieve ENTRY_DELETE events > for the files within the subdirectory. - I assume that this is normal, > although I don't understand the random behavior of getting or not > getting events regarding the files. > > 3 - If I try to delete a subdirectory tree - that is a subdirectory > with nested directories - then Windows Explorer does not let me delete > the tree. The WatchService seems to block this. I can however, delete > this tree by starting at the bottom (leaf) directories and delete them > one at a time. This corresponds essentially to the scenario described > in 2. - This may be normal, but is certainly not convenient. Is this a > Windows feature? > > 4 - Contrary to the documentation (tutorial on WatchService), the > WatchKey remains valid (isValid()) after deletion of the associated > directory. That is, the expression (dir.notExists() && key.isValid()), > where key is the WatchKey associated with dir is true. The first part > of the expression confirms that dir is deleted, and the second part > should be false if the key is automatically cancelled. - I don' think > this is normal at all! > > Thanks for any comments you may have, > For item 3, yes, unfortunately if you are watching a directory then Windows prevents you deleting or moving the directory's parent. It's not a problem deleting the directory that is being watched, it's the parent that is the issue. We have a bug tracking it: http://bugs.sun.com/view_bug.do?bug_id=6972833 but I don't think there is anything we can do because it seems to be a Windows limitation. I'm interested if you can create a test case to demonstrate item 4. When a watched directory is deleted then we get a notification from Windows (via a completion port) and that causes the key to be invalidated. We have various test cases for this and I'm not aware of any issues. -Alan From wolfgang.baltes at laposte.net Thu Dec 16 10:17:23 2010 From: wolfgang.baltes at laposte.net (Wolfgang Baltes) Date: Thu, 16 Dec 2010 10:17:23 -0800 Subject: WatchService In-Reply-To: <4D0A26C9.5000105@oracle.com> References: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> <4D0A26C9.5000105@oracle.com> Message-ID: <4D0A57B3.3010108@laposte.net> On 2010-12-16 06:48, Alan Bateman wrote: > > wolfgang.baltes wrote: >> >> Hi, >> >> I have started to use the WatchService and would like to get >> confirmation for some of my observations. At least one of them is not >> in agreement with the documentation. >> >> My system is Windows 7 Ultimate 64bit with JDK7-b121 32bit and using >> Eclipse 3.61 32bit as the development platform. I am writing a piece >> of code that watches one or several directories recursively or not >> for file additions and deletions. >> >> My observations are for a directory tree where all >> directories/subdirectories are being watched. I use Windows Explorer >> to copy files and directory trees into this directory tree and to >> delete them. >> >> 1 - If I delete a file at any level in the tree, then I get the >> ENTRY_DELETE event for the file and an ENTRY_MODIFIED event for its >> parent directory. - This should be normal. >> >> 2 - If I delete a subdirectory that contains files but no further >> subdirectories, then I receive an ENTRY_DELETE event for the >> subdirectory and an ENTRY_MODIFIED event for its parent directory. In >> addition - and only sometimes - I also receieve ENTRY_DELETE events >> for the files within the subdirectory. - I assume that this is >> normal, although I don't understand the random behavior of getting or >> not getting events regarding the files. >> >> 3 - If I try to delete a subdirectory tree - that is a subdirectory >> with nested directories - then Windows Explorer does not let me >> delete the tree. The WatchService seems to block this. I can however, >> delete this tree by starting at the bottom (leaf) directories and >> delete them one at a time. This corresponds essentially to the >> scenario described in 2. - This may be normal, but is certainly not >> convenient. Is this a Windows feature? >> >> 4 - Contrary to the documentation (tutorial on WatchService), the >> WatchKey remains valid (isValid()) after deletion of the associated >> directory. That is, the expression (dir.notExists() && >> key.isValid()), where key is the WatchKey associated with dir is >> true. The first part of the expression confirms that dir is deleted, >> and the second part should be false if the key is automatically >> cancelled. - I don' think this is normal at all! >> >> Thanks for any comments you may have, >> > For item 3, yes, unfortunately if you are watching a directory then > Windows prevents you deleting or moving the directory's parent. It's > not a problem deleting the directory that is being watched, it's the > parent that is the issue. We have a bug tracking it: > http://bugs.sun.com/view_bug.do?bug_id=6972833 > > but I don't think there is anything we can do because it seems to be a > Windows limitation. > > I'm interested if you can create a test case to demonstrate item 4. > When a watched directory is deleted then we get a notification from > Windows (via a completion port) and that causes the key to be > invalidated. We have various test cases for this and I'm not aware of > any issues. > > -Alan > > Thanks, Alan for the quick reply. I am happy to see that my observations were correct, at least 1 to 3, with 4 needing to be confirmed. I will spend some time on it today to make a small program that displays the behavior. My application is an OSGi bundle which requires quite some heavy lifting for such a small thing. Wolfgang. From wolfgang.baltes at laposte.net Thu Dec 16 12:43:26 2010 From: wolfgang.baltes at laposte.net (Wolfgang Baltes) Date: Thu, 16 Dec 2010 12:43:26 -0800 Subject: WatchService In-Reply-To: <4D0A57B3.3010108@laposte.net> References: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> <4D0A26C9.5000105@oracle.com> <4D0A57B3.3010108@laposte.net> Message-ID: <4D0A79EE.5000002@laposte.net> On 2010-12-16 10:17, Wolfgang Baltes wrote: > > > On 2010-12-16 06:48, Alan Bateman wrote: >> >> wolfgang.baltes wrote: >>> >>> Hi, >>> >>> I have started to use the WatchService and would like to get >>> confirmation for some of my observations. At least one of them is >>> not in agreement with the documentation. >>> >>> My system is Windows 7 Ultimate 64bit with JDK7-b121 32bit and using >>> Eclipse 3.61 32bit as the development platform. I am writing a piece >>> of code that watches one or several directories recursively or not >>> for file additions and deletions. >>> >>> My observations are for a directory tree where all >>> directories/subdirectories are being watched. I use Windows Explorer >>> to copy files and directory trees into this directory tree and to >>> delete them. >>> >>> 1 - If I delete a file at any level in the tree, then I get the >>> ENTRY_DELETE event for the file and an ENTRY_MODIFIED event for its >>> parent directory. - This should be normal. >>> >>> 2 - If I delete a subdirectory that contains files but no further >>> subdirectories, then I receive an ENTRY_DELETE event for the >>> subdirectory and an ENTRY_MODIFIED event for its parent directory. >>> In addition - and only sometimes - I also receieve ENTRY_DELETE >>> events for the files within the subdirectory. - I assume that this >>> is normal, although I don't understand the random behavior of >>> getting or not getting events regarding the files. >>> >>> 3 - If I try to delete a subdirectory tree - that is a subdirectory >>> with nested directories - then Windows Explorer does not let me >>> delete the tree. The WatchService seems to block this. I can >>> however, delete this tree by starting at the bottom (leaf) >>> directories and delete them one at a time. This corresponds >>> essentially to the scenario described in 2. - This may be normal, >>> but is certainly not convenient. Is this a Windows feature? >>> >>> 4 - Contrary to the documentation (tutorial on WatchService), the >>> WatchKey remains valid (isValid()) after deletion of the associated >>> directory. That is, the expression (dir.notExists() && >>> key.isValid()), where key is the WatchKey associated with dir is >>> true. The first part of the expression confirms that dir is deleted, >>> and the second part should be false if the key is automatically >>> cancelled. - I don' think this is normal at all! >>> >>> Thanks for any comments you may have, >>> >> For item 3, yes, unfortunately if you are watching a directory then >> Windows prevents you deleting or moving the directory's parent. It's >> not a problem deleting the directory that is being watched, it's the >> parent that is the issue. We have a bug tracking it: >> http://bugs.sun.com/view_bug.do?bug_id=6972833 >> >> but I don't think there is anything we can do because it seems to be >> a Windows limitation. >> >> I'm interested if you can create a test case to demonstrate item 4. >> When a watched directory is deleted then we get a notification from >> Windows (via a completion port) and that causes the key to be >> invalidated. We have various test cases for this and I'm not aware of >> any issues. >> >> -Alan >> >> > Thanks, Alan for the quick reply. > > I am happy to see that my observations were correct, at least 1 to 3, > with 4 needing to be confirmed. I will spend some time on it today to > make a small program that displays the behavior. My application is an > OSGi bundle which requires quite some heavy lifting for such a small > thing. > > Wolfgang. > > > Hi Alan, I took the WatchDir sample code and modified it as follows: - The directory parsing and event loop runs in a separate thread, which allows me to delete files and directories programmatically. - Added a few extra console outputs to better catch what is going on. - In the event loop, added a section to catch the particular condition in which we are interested. The bottom line of what I found is that the behavior changes depending on whether the deleted subdirectory is empty or not. To reproduce: 1: Change the code to create a parent directory to your liking. This is in line 241: final Path dir = Paths.get("c:\\watchtest"); 2: Run the code without other modification. It will create the before mentioned directory, plus a subdirectory, plus two files in that subdirectory, then waits for something to happen. 3: Manually delete "subdir". The output is: Scanning c:\watchtest ... register: c:\watchtest register: c:\watchtest\subdir Done with registering directories. ENTRY_DELETE: c:\watchtest\subdir c:\watchtest\subdir does not exist... ... but key is valid. ENTRY_MODIFY: c:\watchtest\subdir\file1.txt ENTRY_MODIFY: c:\watchtest\subdir\file2.txt 4: Kill the thread and start over. 5: Manually delete first the two files in subdir, and then subdir. The output is: Scanning c:\watchtest ... register: c:\watchtest register: c:\watchtest\subdir Done with registering directories. ENTRY_DELETE: c:\watchtest\subdir\file1.txt ENTRY_MODIFY: c:\watchtest\subdir ENTRY_DELETE: c:\watchtest\subdir\file2.txt ENTRY_MODIFY: c:\watchtest\subdir Removing watch key for c:\watchtest\subdir. ENTRY_DELETE: c:\watchtest\subdir 6: You can kill the watch thread by deleting directory "watchtest". 7: You can remove the comments from lines 265 to 273 to automate step 5. For me it is important to make step 3 above work correctly. This is what a user would do when a directory needs to be removed manually. I hope this helps. Please let me know how I can be of further help. Wolfgang. package test; import static java.nio.file.LinkOption.NOFOLLOW_LINKS; import java.io.IOException; import java.nio.file.FileRef; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardWatchEventKind; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.Attributes; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** * Example to watch a directory (or tree) for changes to files. */ public class WatchDir { /** * Thread to process watch events. */ private static class WatchThread extends Thread { private final Path dir; private final boolean recursive; public WatchThread(final Path dir, final boolean recursive) { this.dir = dir; this.recursive = recursive; } /** @see java.lang.Thread#run() */ @Override public void run() { try { new WatchDir(this.dir, this.recursive).processEvents(); } catch (final IOException ignore) { } } } private final WatchService watcher; private final Map keys; private final boolean recursive; private final Path dir; private boolean trace = true; @SuppressWarnings("unchecked") static WatchEvent cast(final WatchEvent event) { return (WatchEvent) event; } /** * Register the given directory with the WatchService */ void register(final Path dir) throws IOException { final WatchKey key = dir.register(this.watcher, StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY); if (this.trace) { final FileRef prev = this.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); } } } this.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() { @Override public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException { WatchDir.this.register(dir); return FileVisitResult.CONTINUE; } }); } /** * Creates a WatchService and registers the given directory */ WatchDir(final Path dir, final boolean recursive) throws IOException { this.watcher = FileSystems.getDefault().newWatchService(); this.keys = new HashMap(); this.recursive = recursive; this.dir = dir; if (recursive) { System.out.format("Scanning %s ...\n", dir); this.registerAll(dir); System.out.println("Done with registering directories."); } else { this.register(dir); } // enable trace after initial registration this.trace = true; } /** * Process all events for keys queued to the watcher */ void processEvents() { Path dir = null; for (;;) { // wait for key to be signalled final WatchKey key; try { key = this.watcher.take(); } catch (final InterruptedException x) { System.out.println("Thread interrupted."); return; } dir = this.keys.get(key); if (dir == null) { System.err.println("WatchKey not recognized!!"); continue; } for (final WatchEvent event : key.pollEvents()) { final WatchEvent.Kind kind = event.kind(); // TBD - provide example of how OVERFLOW event is handled if (kind == StandardWatchEventKind.OVERFLOW) { continue; } // Context for directory entry event is the file name of entry final WatchEvent ev = WatchDir.cast(event); final Path name = ev.context(); final 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 (this.recursive && (kind == StandardWatchEventKind.ENTRY_CREATE)) { try { if (Attributes.readBasicFileAttributes(child, NOFOLLOW_LINKS) .isDirectory()) { this.registerAll(child); } } catch (final IOException x) { // ignore to keep sample readbale } } // if event is DELETE ... if (kind == StandardWatchEventKind.ENTRY_DELETE) { WatchKey ckey = null; for (final Entry e : this.keys.entrySet()) { if (e.getValue().equals(child)) { ckey = e.getKey(); break; } } // ... and child is a directory and it is effectively deleted. if ((ckey != null) && child.notExists()) { System.out.format("%s does not exist... ", child); if (ckey.isValid()) { System.out.println("... but key is valid."); } else { System.out.println("... and key is cancelled."); } } } } // reset key and remove from set if directory no longer accessible final boolean valid = key.reset(); if (!valid) { System.out.format("Removing watch key for %s.\n", dir); this.keys.remove(key); // all directories are inaccessible if (this.keys.isEmpty()) { break; } } } } /** * TODO method description * * @param args TODO parameter description * * @throws IOException TODO exception description */ public static void main(final String[] args) throws IOException { // parse arguments final boolean recursive = true; final Path dir = Paths.get("c:\\watchtest"); try { dir.createDirectory(); } catch (final Exception ignore) { } // final WatchThread t = new WatchThread(dir, recursive); t.start(); // final Path subdir = dir.resolve(Paths.get("subdir")); subdir.createDirectory(); final Path file1 = subdir.resolve(Paths.get("file1.txt")); file1.createFile(); final Path file2 = subdir.resolve(Paths.get("file2.txt")); file2.createFile(); // try { Thread.sleep(200); } catch (final InterruptedException e) { } // // Comment out this section vvvv // file1.delete(); // file2.delete(); // subdir.delete(); // try { // Thread.sleep(500); // } // catch (final InterruptedException e) { // } // t.interrupt(); // Comment out this section ^^^^ } } From Alan.Bateman at oracle.com Thu Dec 16 13:28:04 2010 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Thu, 16 Dec 2010 21:28:04 +0000 Subject: WatchService In-Reply-To: <4D0A79EE.5000002@laposte.net> References: <1728174.485578.1292455140760.JavaMail.www@wwinf8212> <4D0A26C9.5000105@oracle.com> <4D0A57B3.3010108@laposte.net> <4D0A79EE.5000002@laposte.net> Message-ID: <4D0A8464.80508@oracle.com> Wolfgang Baltes wrote: > Hi Alan, > > I took the WatchDir sample code and modified it as follows: > - The directory parsing and event loop runs in a separate thread, > which allows me to delete files and directories programmatically. > - Added a few extra console outputs to better catch what is going on. > - In the event loop, added a section to catch the particular condition > in which we are interested. > > The bottom line of what I found is that the behavior changes depending > on whether the deleted subdirectory is empty or not. Thanks for spending time on a test and instructions on how to duplicate. Unfortunately I'm away for a few days but I will look at it when I get back and then we will know if this is a bug in our WatchService implementation on Windows or something else. -Alan