Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.hg/
_darcs/
.cabal-sandbox/
cabal.sandbox.config
test/.test.json.swp
*~
dist/
*.prof
Expand Down
13 changes: 13 additions & 0 deletions linux-inotify.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ library

ghc-options: -Wall

test-suite test
hs-source-dirs:
src,
test
type:
exitcode-stdio-1.0
main-is:
test.hs
build-depends:
base >= 4.7 && < 5,
unix,
linux-inotify

source-repository head
type: git
location: http://github.com/lpsmith/linux-inotify
Expand Down
7 changes: 4 additions & 3 deletions src/System/Linux/Inotify.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ import Prelude hiding (init)

import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Control.Applicative
import Data.Monoid
-- import Control.Applicative
-- import Data.Monoid
-- https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10#GHCsaysTheimportof...isredundant
import Data.Typeable
import Data.Function ( on )
import Data.Word
Expand Down Expand Up @@ -325,7 +326,7 @@ data Event = Event
-- to the watched directory.
--
-- The proper Haskell interpretation of this seems to be to use
-- 'GHC.IO.Encoding.getFileSystemEncoding' and then unpack it to a
-- 'GHC.IO.Encoding.getFileSystemEncoding' and then unpack it to a
-- 'String' or decode it using the text package.
} deriving (Eq, Show, Typeable)

Expand Down
64 changes: 64 additions & 0 deletions test/test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Main where

import System.Environment
import System.Exit
import Prelude hiding (reverse, log)
import qualified System.Linux.Inotify as IN
import Data.Monoid(mconcat)
import Control.Monad(forever)
import Control.Exception(bracket)
import GHC.Conc.Sync(ThreadId)
import Data.IORef (IORef, newIORef, atomicModifyIORef', readIORef)
import System.Posix.Signals(installHandler, Handler(Catch), sigINT, sigTERM, raiseSignal)
import Control.Concurrent(forkIO, threadDelay)
import Control.Concurrent.MVar(newEmptyMVar, takeMVar, putMVar, MVar)

log :: String -> IO()
log x = putStrLn $ "[linux-inotify]: " ++ x

events :: IN.Mask a
events = mconcat [IN.in_MODIFY]

initFileReload :: IORef Int -> String -> IO ThreadId
initFileReload counter dir = do
forkIO.bracket IN.init IN.close $ \ind -> do
_ <- IN.addWatch ind dir events
forever $ do
e <- IN.getEvent ind
log $ show e
atomicModifyIORef' counter (\n -> (n + 1, ()))

testFileWrite :: String -> IO ()
testFileWrite path = do
writeFile path "test"
log "Test writing to file"
threadDelay $ 1
raiseSignal sigINT
-- sigTERM will not be caught :/

handler :: MVar () -> IO ()
handler s_interrupted =
putMVar s_interrupted ()

recvFunction :: IORef Int -> MVar () -> IO ()
recvFunction counter signal = do
output <- takeMVar signal
n <- readIORef counter
log $ "Interrupt Received. Stopping watcher" ++ show n
if n == 1
then exitSuccess
else exitFailure

main:: IO()
main = do
-- [file] <- getArgs
-- https://github.com/haskell/cabal/issues/4643
let file = "test/test.json"
counter <- newIORef 0
log $ "watching file: " ++ file
_ <- initFileReload counter file
testFileWrite file
s_interrupted <- newEmptyMVar
installHandler sigTERM (Catch $ handler s_interrupted) Nothing
installHandler sigINT (Catch $ handler s_interrupted) Nothing
recvFunction counter s_interrupted
1 change: 1 addition & 0 deletions test/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test