-
Notifications
You must be signed in to change notification settings - Fork 4
prevents files from being opened/read in callback? #3
Description
I'm trying to track down a bug in static site generator Hakyll's master branch (i.e. unreleased) which now uses fs-notify for automatic recompilation in conjunction with a preview server, i.e. to be able to preview one's site while editing it. As a consequence, Hakyll's preview functionality (which depends on this package) is now broken in Windows.
I believe I have found two problems which can be traced back to win32-notify.
-
Programs using win32-notify (most likely indirectly through fs-notify) have to be compiled with
-threadedor win32-notify will block all other threads. If a file under watch (withwatchTree) is saved such that it triggers the callback, the main/other threads are afforded a time slice. I'm not familiar with the implications of-threaded, but I don't think it's a big deal. I'm just noting here because it took me a while to figure out why my program was being blocked (wouldn't even respond to CTRL+C; had to terminate through task manager). -
The file for which the event was triggered cannot be opened in the callback (e.g.
withreadFile). Trying to do so leads to an error.readfile.exe: provider\pages\about.markdown: openFile: permission denied (Permission denied)
However, any other file being
watchTree'ed can be opened in the callback (as long as it's not the one for which the event was fired).
I'm not familiar with the ReadDirectoryChangesW function/API. However, win32-notify does seem to use flags (fILE_SHARE_READ .|. fILE_SHARE_WRITE) which I've read in two different places is what you would want in order to be able to open the files being watched.
The following code replicates the issue:
import qualified Filesystem.Path.CurrentOS as FP
import System.FSNotify
import Control.Monad
import Control.Monad.Trans (liftIO)
import System.FilePath
import Control.Concurrent
main :: IO ()
main = do
let provider = FP.decodeString "provider"
manager <- startManagerConf (Debounce 0.1)
watchTree manager provider (const True) $ \event -> do
putStrLn "EVENT ==========================="
let path = FP.encodeString $ eventPath event
putStrLn $ " " ++ path
contents <- readFile ("provider" </> path)
putStrLn $ " " ++ contents
threadDelay 36000000
where
preServeHook _ = return ()I'm trying to find the cause of this but I'm not very familiar with the Win32 API, so I'd appreciate any leads or ideas.