Skip to content

prevents files from being opened/read in callback? #3

@blaenk

Description

@blaenk

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.

  1. Programs using win32-notify (most likely indirectly through fs-notify) have to be compiled with -threaded or win32-notify will block all other threads. If a file under watch (with watchTree) 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).

  2. The file for which the event was triggered cannot be opened in the callback (e.g.
    with readFile). 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions