haskell-fswatch / hfsnotify

Unified Haskell interface for basic file system notifications
BSD 3-Clause "New" or "Revised" License
136 stars 40 forks source link

Using NativeManager on Linux, moving a watched directory results in incorrect behavior #54

Open mlacorte opened 9 years ago

mlacorte commented 9 years ago
Description

After moving a directory that hfsnotify is watching, hfsnotify reports changes inside that directory as if it had not been moved.

Only the NativeManager on Linux is affected.

I have not tested the NativeManager on OS X or Windows.

Steps to Reproduce
  1. Run the following Bash script:

    mkdir -p /tmp/example
  2. Run the following Haskell program:

    {-# LANGUAGE OverloadedStrings #-}
    
    import System.FSNotify
    import Control.Concurrent
    import Control.Monad
    
    main :: IO ()
    main = withManager $ \mgr -> do
      _ <- watchTree mgr "/tmp/example" (const True) print
      forever (threadDelay maxBound)
  3. While the Haskell program is running, run the following Bash script:

    cd /tmp/example
    
    mkdir foo
    touch foo/test
    
    mv foo bar
    
    touch bar/test
    rm -rf bar
    Expected Output
Added (FilePath "/tmp/example/foo/test") <TIMESTAMP>
Removed (FilePath "/tmp/example/foo/test") <TIMESTAMP>
Added (FilePath "/tmp/example/bar/test") <TIMESTAMP>
Modified (FilePath "/tmp/example/bar/test") <TIMESTAMP>
Removed (FilePath "/tmp/example/bar/test") <TIMESTAMP>
Actual Output

The following is printed from the Haskell program:

Added (FilePath "/tmp/example/foo/test") <TIMESTAMP>
Modified (FilePath "/tmp/example/foo/test") <TIMESTAMP>
Removed (FilePath "/tmp/example/foo/test") <TIMESTAMP>
gregwebs commented 9 years ago

My guess is that on the whole the behavior around moving a directory that is watched is undefined. We probably need to allow the user to specify whether a directory should be watched after moved, but a possible default that may work cross-platform is to stop watching it.

thomasjm commented 6 years ago

This is just how inotify works--when you move the directory it is moving the inode but it's still watching the same inode.

Solution: we should detect the IN_MOVED_FROM and IN_MOVED_TO events and emit events/update watches accordingly. For example, if a folder is moved outside of a watched tree, we should stop watching it entirely.

erikd commented 6 years ago

Just got hit by a variant on this myself using the conduit version.