summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assistant/Watcher.hs8
-rw-r--r--Utility/Kqueue.hs13
-rw-r--r--Utility/libkqueue.c55
3 files changed, 40 insertions, 36 deletions
diff --git a/Assistant/Watcher.hs b/Assistant/Watcher.hs
index 52c3780ab..13c27d080 100644
--- a/Assistant/Watcher.hs
+++ b/Assistant/Watcher.hs
@@ -84,10 +84,12 @@ watchThread st dstatus changechan = withINotify $ \i -> do
}
#else
#ifdef WITH_KQUEUE
-watchThread st dstatus changechan = forever $ do
+watchThread st dstatus changechan = do
dirs <- scanRecursive "." ignored
- changeddir <- waitChange dirs
- print $ "detected a change in " ++ show changeddir
+ kqueue <- initKqueue dirs
+ forever $ do
+ changeddir <- waitChange kqueue
+ print $ "detected a change in " ++ show changeddir
#else
watchThread = undefined
#endif /* WITH_KQUEUE */
diff --git a/Utility/Kqueue.hs b/Utility/Kqueue.hs
index a3d8aff2d..6da97d3fa 100644
--- a/Utility/Kqueue.hs
+++ b/Utility/Kqueue.hs
@@ -11,6 +11,10 @@ module Utility.Kqueue (
scanRecursive,
addSubDir,
removeSubDir,
+
+ initKqueue,
+ stopKqueue,
+
waitChange,
) where
@@ -18,7 +22,6 @@ import Common
import System.Posix.Types
import Foreign.C.Types
-import Foreign.C.Error
import Foreign.Ptr
import Foreign.Marshal
import qualified Data.Map as M
@@ -52,17 +55,17 @@ foreign import ccall unsafe "libkqueue.h waitchange_kqueue" c_waitchange_kqueue
{- Initializes a Kqueue to watch a map of directories. -}
initKqueue :: DirMap -> IO Kqueue
-initKqueue dirmap = withArrayLen (M.keys dirmap) $ \fdcnt c_fds ->
+initKqueue dirmap = withArrayLen (M.keys dirmap) $ \fdcnt c_fds -> do
h <- c_init_kqueue (fromIntegral fdcnt) c_fds
return $ Kqueue h dirmap
{- Stops a Kqueue. Note: Does not directly close the Fds in the dirmap,
- so it can be reused. -}
-stopKqueue :: Kqueue -> IO
+stopKqueue :: Kqueue -> IO ()
stopKqueue (Kqueue h _) = closeFd h
{- Waits for a change on a Kqueue, and returns the directory
- - or directories where a change took place.
+ - where a change took place.
-
- The kqueue interface does not tell what type of change took place in
- the directory; it could be an added file, a deleted file, a renamed
@@ -71,7 +74,7 @@ stopKqueue (Kqueue h _) = closeFd h
-
- Note that if subdirectories have changed, the caller should re-run
- initKqueue to get them watched. -}
-waitChange :: Kqueue -> IO [FilePath]
+waitChange :: Kqueue -> IO (Maybe FilePath)
waitChange (Kqueue h dirmap) = do
changed <- c_waitchange_kqueue h
return $ M.lookup changed dirmap
diff --git a/Utility/libkqueue.c b/Utility/libkqueue.c
index a919a60c7..999508f7e 100644
--- a/Utility/libkqueue.c
+++ b/Utility/libkqueue.c
@@ -13,10 +13,35 @@
#include <sys/event.h>
#include <sys/time.h>
+/* The specified fds are added to the set of fds being watched for changes.
+ * Fds passed to prior calls still take effect, so it's most efficient to
+ * not pass the same fds repeatedly.
+ */
+signed int helper(const int kq, const int fdcnt, const int *fdlist,
+ struct timespec *timeout) {
+ int i, nev;
+ struct kevent evlist[1];
+ struct kevent chlist[fdcnt];
+
+ for (i = 0; i < fdcnt; i++) {
+ EV_SET(&chlist[i], fdlist[i], EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_WRITE,
+ 0, 0);
+ }
+
+ nev = kevent(kq, chlist, fdcnt, evlist, 1, timeout);
+
+ if (nev == 1)
+ return evlist[0].ident;
+ else
+ return -1;
+}
+
/* Initializes a kqueue, with a list of fds to watch for changes.
* Returns the kqueue's handle. */
int init_kqueue(const int fdcnt, const int *fdlist) {
- struct nodelay = {0, 0};
+ struct timespec nodelay = {0, 0};
int kq;
if ((kq = kqueue()) == -1) {
@@ -36,31 +61,5 @@ int init_kqueue(const int fdcnt, const int *fdlist) {
* Returns the fd that changed, or -1 on error.
*/
signed int waitchange_kqueue(const int kq) {
- helper(kq, 0, NULL, NULL);
-}
-
-/* The specified fds are added to the set of fds being watched for changes.
- * Fds passed to prior calls still take effect, so it's most efficient to
- * not pass the same fds repeatedly.
- */
-signed int helper(const int kq, const int fdcnt, const int *fdlist, cont struct *timeout) {
- int i, nev;
- struct kevent evlist[1];
- struct kevent chlist[fdcnt];
-
- for (i = 0; i < fdcnt; i++) {
- EV_SET(&chlist[i], fdlist[i], EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_CLEAR,
- NOTE_WRITE,
- 1,
- timeout);
- }
-
- nev = kevent(info->kq, info->chlist, info->cnt, info->evlist,
- 1, NULL);
-
- if (nev == 1)
- return evlist[0].ident;
- else
- return -1;
+ return helper(kq, 0, NULL, NULL);
}