0

Our products currently using JDK 1.6, so we have to rely on JNotify for file system changes. However during the test I noticed something that worked perfect in my Win 7 development environment stop working in XP and win server 2003. So I move on to wrote a small test program. Here is what it roughly looks like.

In the main class I only have this:

public static void main(String[] args) {
    SyncUtil instance = new SyncUtil();
    instance.start();

    Scanner s = new Scanner(System.in);
    s.nextLine();
}

SyncUtil is a class that extends Threads:

    public void run() {
        String path = "D:\\testFolder";
        int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
        boolean watchSubtree = true;
        File file = null;
        try {
            JNotify.addWatch(path, mask, watchSubtree, new Listener());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

The Listener class don't have any work inside, It just print log. Now, If I run the above sample on Windows 7 / 8. It will work just fine. But when I test it on my Win Server 2003, JNotify just stop working and Listener will not print any log at all.

What's more interesting though is if I try to make SyncUtil wait a minute when after its work. If I add:

Thread.sleep(60000);

to the end of the run function to make it wait for 60 seconds. And instead of monitoring 1 folder, this time I'll monitor 2, I'll call them folder A and B.

What happens on the Win Server 2003 machine in this case is that if I add a file to folder A within the 60s waiting time, JNotify will properly react to the event and print a log. And it will even keep on working even if 60s has passed and the SyncUtil Thread is terminated. But now I add a file to folder B (after the 60s waiting time that is), nothing will be printed.

To sum it up, the symptom is: 1. On win 7 and win 8, JNotify will keep on working disregard of whether or not the thread calls for JNotify.addWatch() is still alive. 2. On win XP and win server 2003, JNotify can properly generate event when The Thread calls JNotify.addWatch() is running. Paths that generated at least one event when that Thread is still alive will continue to be monitored after that thread is terminated. But those paths that didn't generate any event when said thread is alive, will not work after that thread is terminated.

Now knowing this pattern I'm currently using a CountDownLatch to fix the issue, but I'm just really curious why this is happening. I feel this kind of don't make any sense, where do you think the problem is? I'm leaning towards the conclusion that maybe windows trigger file system event differently? Do you think this might be the case?

AERYEN
  • 21
  • 2

1 Answers1

0

this is very weird, but: adding a watch is a really quick operation, why are you adding them in a thread?

Omry Yadan
  • 31,280
  • 18
  • 64
  • 87
  • I'm a little bit lost at your question, do you mean "why" instead of "what"? if that's the case, well in fact the sample I shown in the question is a test program intend to mimic what's happening in a larger project. In that project, we have a class that use a "in-line thread" to do some side tasks and JNotify just happened to be one of them. I sure can take JNotify out of that thread, but well... I know how to fix this strange behavior, I'm just scratching my head wondering why you know. :-) – AERYEN Sep 07 '13 at 04:49
  • yeah, I meant why. As far as I can remember (it's been many years since I wrote JNotify) - JNotify on Windows does not care at all about which thread is adding the watch. the reason the code sample mentions sleep is that without it the JVM exits in the simple example there. it's not a problem for a real world program. – Omry Yadan Sep 07 '13 at 07:20
  • Oh, to prevent the simple example from exiting, I've put s.nextLine() in the main function you see. That keeps the main thread alive. – AERYEN Sep 07 '13 at 08:35
  • as a workaround, try to schedule all watch add and remove to the same thread that will remain alive for the lifetime of your app. this is really weird and will require some digging into to figure out. (maybe enabling debug in the native code and see if anything weird is going on). – Omry Yadan Sep 07 '13 at 18:18