diff --git a/ANNOUNCE b/ANNOUNCE
deleted file mode 100644
--- a/ANNOUNCE
+++ /dev/null
@@ -1,58 +0,0 @@
-Greetings!
-
-I'm pleased to announce hinotify 0.1, a library to inotify[1] which has
-been part of the Linux kernel since 2.6.13.
-
-inotify provides file system event notification, simply add a watcher to
-a file or directory and get an event when it is accessed or modified.
-
-The API basically consists of:
-
-inotify_init :: IO INotify
-inotify_add_watch :: INotify
-                  -> [EventVariety]   -- different events to listen on
-                  -> FilePath         -- file/directory to watch
-                  -> (Event -> IO ()) -- event handler
-                  -> IO WatchDescriptor
-inotify_rm_watch :: INotify -> WatchDescriptor -> IO ()
-
-A sample program:
-
-> import System.Directory
-> import System.IO
->
-> import System.INotify
->
-> main :: IO ()
-> main = do
->     inotify <- inotify_init
->     print inotify
->     home <- getHomeDirectory
->     wd <- inotify_add_watch inotify
->                             [Open,Close,Access,Modify,Move]
->                             home
->                             print
->     print wd
->     putStrLn "Listens to your home directory. Hit enter to terminate."
->     getLine
->     inotify_rm_watch inotify wd
-
-The code is available via www:
-
-http://haskell.org/~kolmodin/code/hinotify/download/hinotify-0.1.tar.gz
-
-and via darcs:
-
-  darcs get http://haskell.org/~kolmodin/code/hinotify/
-
-The API is available at:
-
-  http://haskell.org/~kolmodin/code/hinotify/docs/api/
-
-The library is very young and I'm most grateful for feedback on the API,
-and what else you might have to suggest.
-
-Cheers,
-  Lennart Kolmodin
-
-[1] http://www.kernel.org/pub/linux/kernel/people/rml/inotify/
diff --git a/Makefile b/Makefile
deleted file mode 100644
--- a/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-
-.PHONY : docs
-
-docs : README.html
-
-%.html : %
-	pandoc -s -S --toc -c hinotify.css $< -o $@
diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 % hinotify: inotify for Haskell
 % Lennart Kolmodin <kolmodin@gentoo.org>
-% December 26, 2007
+% December 26, 2007-2009
 
 About
 -----
@@ -11,7 +11,7 @@
 inotify provides file system event notification, simply add a watcher to
 a file or directory and get an event when it is accessed or modified.
 
-This module is named `inotify`.
+This module is named `hinotify`.
 
 See example code in the `examples` directory, distributed with the source
 code.
@@ -20,6 +20,9 @@
 
 News
 ----
+
+**hinotify 0.3**
+:   * Compiles with GHC 6.12, GHC 6.10.4, GHC 6.8.2 and GHC 6.6.1
 
 **hinotify 0.2**
 :   * Updates to the API
diff --git a/README.html b/README.html
deleted file mode 100644
--- a/README.html
+++ /dev/null
@@ -1,179 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml"
-><head
-  ><title
-    >hinotify: inotify for Haskell</title
-    ><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"
-     /><meta name="generator" content="pandoc"
-     /><meta name="author" content="Lennart Kolmodin &lt;kolmodin@gentoo.org&gt;"
-     /><meta name="date" content="December 26, 2007"
-     /><link rel="stylesheet" href="hinotify.css" type="text/css" media="all" />
-</head
-  ><body
-  ><h1 class="title"
-    >hinotify: inotify for Haskell</h1
-    ><div id="toc"
-    ><ul
-      ><li
-	><a href="#about" id="TOC-about"
-	  >About</a
-	  ></li
-	><li
-	><a href="#news" id="TOC-news"
-	  >News</a
-	  ></li
-	><li
-	><a href="#api" id="TOC-api"
-	  >API</a
-	  ></li
-	><li
-	><a href="#download" id="TOC-download"
-	  >Download</a
-	  ></li
-	><li
-	><a href="#author" id="TOC-author"
-	  >Author</a
-	  ></li
-	><li
-	><a href="#legal" id="TOC-legal"
-	  >Legal</a
-	  ></li
-	></ul
-      ></div
-    ><h2 id="about"
-    ><a href="#TOC-about"
-      >About</a
-      ></h2
-    ><p
-    >hinotify, a library to <a href="http://www.kernel.org/pub/linux/kernel/people/rml/inotify/"
-      >inotify</a
-      > which has been part of the Linux kernel since 2.6.13.</p
-    ><p
-    >inotify provides file system event notification, simply add a watcher to a file or directory and get an event when it is accessed or modified.</p
-    ><p
-    >This module is named <code
-      >inotify</code
-      >.</p
-    ><p
-    >See example code in the <code
-      >examples</code
-      > directory, distributed with the source code.</p
-    ><h2 id="news"
-    ><a href="#TOC-news"
-      >News</a
-      ></h2
-    ><dl
-    ><dt
-      ><strong
-	>hinotify 0.2</strong
-	></dt
-      ><dd
-      ><ul
-	><li
-	  >Updates to the API<ul
-	    ><li
-	      >Function names is now in semiCamelCase</li
-	      ><li
-	      >Restructure event parameters to make it more consistent</li
-	      ></ul
-	    ></li
-	  ><li
-	  >Small test suit in <code
-	    >tests/</code
-	    ></li
-	  ><li
-	  >Compiles with GHC 6.8.2 and GHC 6.6.1</li
-	  ><li
-	  >Requires Cabal 1.2</li
-	  ></ul
-	></dd
-      ><dt
-      ><strong
-	>hinotify 0.1</strong
-	></dt
-      ><dd
-      >Initial release</dd
-      ></dl
-    ><h2 id="api"
-    ><a href="#TOC-api"
-      >API</a
-      ></h2
-    ><p
-    >The API basically consists of:</p
-    ><pre
-    ><code
-      >initINotify :: IO INotify
-addWatch :: INotify
-         -&gt; [EventVariety]   -- different events to listen on
-         -&gt; FilePath         -- file/directory to watch
-         -&gt; (Event -&gt; IO ()) -- event handler
-         -&gt; IO WatchDescriptor
-removeWatch :: INotify -&gt; WatchDescriptor -&gt; IO ()
-</code
-      ></pre
-    ><p
-    >A sample program:</p
-    ><pre
-    ><code
-      >import System.Directory
-import System.IO
-
-import System.INotify
-
-main :: IO ()
-main = do
-    inotify &lt;- initINotify
-    print inotify
-    home &lt;- getHomeDirectory
-    wd &lt;- addWatch
-            inotify
-            [Open,Close,Access,Modify,Move]
-            home
-            print
-    print wd
-    putStrLn &quot;Listens to your home directory. Hit enter to terminate.&quot;
-    getLine
-    removeWatch inotify wd
-</code
-      ></pre
-    ><h2 id="download"
-    ><a href="#TOC-download"
-      >Download</a
-      ></h2
-    ><p
-    >The code is available via the <a href="http://haskell.org/~kolmodin/code/hinotify/"
-      >homepage</a
-      >, and via darcs:</p
-    ><pre
-    ><code
-      >darcs get --partial http://haskell.org/~kolmodin/code/hinotify/
-</code
-      ></pre
-    ><p
-    >The <a href="http://haskell.org/~kolmodin/code/hinotify/docs/api/"
-      >API</a
-      > is available online.</p
-    ><p
-    >I&rsquo;m most grateful for feedback on the API, and what else you might have to suggest.</p
-    ><h2 id="author"
-    ><a href="#TOC-author"
-      >Author</a
-      ></h2
-    ><p
-    >Lennart Kolmodin</p
-    ><p
-    ><code
-      >kolmodin at gentoo.org</code
-      ></p
-    ><h2 id="legal"
-    ><a href="#TOC-legal"
-      >Legal</a
-      ></h2
-    ><p
-    >This software is released under a BSD-style license. See LICENSE for more details.</p
-    ><p
-    >Copyright © 2007 Lennart Kolmodin</p
-    ></body
-  ></html
->
-
diff --git a/examples/DirTree/DirTree.hs b/examples/DirTree/DirTree.hs
deleted file mode 100644
--- a/examples/DirTree/DirTree.hs
+++ /dev/null
@@ -1,111 +0,0 @@
--- Duncan Coutts 2006-2007
--- Requires gtk2hs 0.9.11
-
-import qualified Data.Map as Map
-import System.Directory
-import System.Environment
-import Control.Concurrent
-
-import Data.IORef
-import Control.Monad (liftM)
-import Ix (inRange)
-
-import System.INotify
-
-import Graphics.UI.Gtk hiding (TreeModelFlags(TreeModelListOnly), cellText)
-import Graphics.UI.Gtk.ModelView.CellLayout
-import Graphics.UI.Gtk.ModelView.Types (TypedTreeModelClass)
-import Graphics.UI.Gtk.ModelView.TreeModel (TreeModelFlags(TreeModelListOnly))
-import Graphics.UI.Gtk.ModelView.CellRendererText (cellText)
-import Graphics.UI.Gtk.ModelView.CustomStore
-import Graphics.UI.Gtk.TreeList.TreeIter
-
-instance TypedTreeModelClass (CustomTreeModel a)
-
-dirModelNew :: FilePath -> IO (CustomTreeModel () FilePath)
-dirModelNew path = do
-  
-  dirContents <- getDirectoryContents path
-  
-  rows <- newIORef (Map.fromList (zip dirContents (repeat ())))
-
-  model <- customTreeModelNew () CustomTreeModelImplementation {
-      customTreeModelGetFlags      = return [TreeModelListOnly],
-      customTreeModelGetIter       = \[n] -> return (Just (TreeIter 0 (fromIntegral n) 0 0)),
-      customTreeModelGetPath       = \(TreeIter _ n _ _) -> return [fromIntegral n],
-      customTreeModelGetRow        = \(TreeIter _ n _ _) ->
-                                     readIORef rows >>= \rows -> 
-                                     if inRange (0, Map.size rows - 1) (fromIntegral n)
-                                       then return (fst $ Map.elemAt (fromIntegral n) rows)
-                                       else fail "DirModel.getRow: iter does not refer to a valid entry",
-
-      customTreeModelIterNext      = \(TreeIter _ n _ _) ->
-                                     readIORef rows >>= \rows ->
-                                        if n >= fromIntegral (Map.size rows) - 1
-                                          then return Nothing
-                                          else return (Just (TreeIter 0 (n+1) 0 0)),
-      customTreeModelIterChildren  = \_ -> return Nothing,
-      customTreeModelIterHasChild  = \_ -> return False,
-      customTreeModelIterNChildren = \index -> readIORef rows >>= \rows ->
-                                           case index of
-                                             Nothing -> return $! Map.size rows
-                                             _       -> return 0,
-      customTreeModelIterNthChild  = \index n -> case index of
-                                               Nothing -> return (Just (TreeIter 0 (fromIntegral n) 0 0))
-                                               _       -> return Nothing,
-      customTreeModelIterParent    = \_ -> return Nothing,
-      customTreeModelRefNode       = \_ -> return (),
-      customTreeModelUnrefNode     = \_ -> return ()
-    }
-
-  notify <- initINotify
-  watch <- addWatch notify [Move, Create, Delete] path $ \event -> 
-    let add file = do 
-          index <- atomicModifyIORef rows (\map ->
-                     let map' = Map.insert file () map
-                      in (map', Map.findIndex file map'))
-          treeModelRowInserted model [index] (TreeIter 0 (fromIntegral index) 0 0)
-        remove file = do
-          index <- atomicModifyIORef rows (\map ->
-                     let map' = Map.delete file map
-                      in (map', Map.findIndex file map))
-          treeModelRowDeleted model [index]
-
-     in case event of
-          MovedIn  _ file _ -> add file
-          MovedOut _ file _ -> remove file
-          Created  _ file   -> add file
-          Deleted  _ file   -> remove file
-          _ -> putStrLn $ "other event: " ++ show event
-
-  -- TODO: on destroy model (INotify.removeWatch watch)
-  
-  return model
-
-main = do
-  initGUI
-
-  win <- windowNew
-  win `onDestroy` mainQuit
-
-  args <- getArgs
-  let dir = case args of
-              [d] -> d
-	      _   -> "."
-
-  model <- dirModelNew dir
-
-  tv <- treeViewNewWithModel model
-  win `containerAdd` tv
-
-  tvc <- treeViewColumnNew
-  treeViewAppendColumn tv tvc
-
-  text <- cellRendererTextNew
-  cellLayoutPackStart tvc text True
-  cellLayoutSetAttributes tvc text model
-    (\file -> [cellText := file])
-
-  widgetShowAll win
-  timeoutAddFull (yield >> return True) priorityDefaultIdle 50
-  mainGUI
diff --git a/examples/simple/simple.hs b/examples/simple/simple.hs
deleted file mode 100644
--- a/examples/simple/simple.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-module Main where
-
-import System.Directory
-import System.IO
-
-import System.INotify
-
-main :: IO ()
-main = do
-    inotify <- initINotify
-    print inotify
-    home <- getHomeDirectory
-    wd <- addWatch inotify [Open,Close,Access,Modify,Move] home print
-    print wd
-    putStrLn "Listens to your home directory. Hit enter to terminate."
-    getLine
-    removeWatch inotify wd
diff --git a/hinotify.cabal b/hinotify.cabal
--- a/hinotify.cabal
+++ b/hinotify.cabal
@@ -1,5 +1,6 @@
 name:               hinotify
-version:            0.2
+version:            0.3
+build-type:         Simple
 synopsis:           Haskell binding to INotify
 description:
     .
@@ -22,7 +23,7 @@
 library
     build-depends:  unix
     if flag(split-base)
-        build-depends:  base >= 3, containers, directory
+        build-depends:  base >= 3 && < 5, containers, directory
     else
         build-depends:  base < 3
     extensions:     ForeignFunctionInterface
@@ -34,5 +35,4 @@
 
     ghc-options:    -fvia-C -Wall
 
-    include-dirs:   include
     hs-source-dirs: src
diff --git a/hinotify.css b/hinotify.css
deleted file mode 100644
--- a/hinotify.css
+++ /dev/null
@@ -1,89 +0,0 @@
-body {
-    margin: auto;
-    padding-right: 1em;
-    padding-left: 1em;
-    max-width: 50em; 
-    border-left: 1px solid black;
-    border-right: 1px solid black;
-    color: black;
-    font-family: Verdana, sans-serif;
-    font-size: 100%;
-    line-height: 140%;
-    color: #333; 
-}
-pre {
-    border: 1px dotted gray;
-    background-color: #9999ff;
-    color: #111111;
-    padding: 0.5em;
-}
-code {
-    font-family: monospace;
-    font-size: 110%;
-}
-h1 a, h2 a, h3 a, h4 a, h5 a { 
-    text-decoration: none;
-    color: #000099; 
-}
-h1, h2, h3, h4, h5 { font-family: verdana;
-                     font-weight: bold;
-                     border-bottom: 1px dotted black;
-                     color: #000099; }
-h1 {
-        font-size: 130%;
-}
-
-h2 {
-        font-size: 110%;
-        border-bottom: 1px dotted black;
-}
-
-h3 {
-        font-size: 95%;
-}
-
-h4 {
-        font-size: 90%;
-        font-style: italic;
-}
-
-h5 {
-        font-size: 90%;
-        font-style: italic;
-}
-
-h1.title {
-        font-size: 150%;
-        font-weight: bold;
-        text-align: left;
-        border: none;
-}
-
-dt code {
-        font-weight: bold;
-}
-dd p {
-        margin-top: 0;
-}
-
-a:link {
-       color: #000099
-       }
-
-a:visited {
-	  color: #666699
-	  }
-a:hover {
-	color: #666699
-	}
-a:active {
-	 color: #000099
-	 }
-
-#footer {
-        padding-top: 1em;
-        font-size: 70%;
-        color: gray;
-        text-align: center;
-}
-
diff --git a/include/inotify-syscalls.h b/include/inotify-syscalls.h
deleted file mode 100644
--- a/include/inotify-syscalls.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef _LINUX_INOTIFY_SYSCALLS_H
-#define _LINUX_INOTIFY_SYSCALLS_H
-
-#include <sys/syscall.h>
-
-#if defined(__i386__)
-# define __NR_inotify_init	291
-# define __NR_inotify_add_watch	292
-# define __NR_inotify_rm_watch	293
-#elif defined(__x86_64__)
-# define __NR_inotify_init	253
-# define __NR_inotify_add_watch	254
-# define __NR_inotify_rm_watch	255
-#elif defined(__powerpc__) || defined(__powerpc64__)
-# define __NR_inotify_init	275
-# define __NR_inotify_add_watch	276
-# define __NR_inotify_rm_watch	277
-#elif defined (__ia64__)
-# define __NR_inotify_init	1277
-# define __NR_inotify_add_watch	1278
-# define __NR_inotify_rm_watch	1279
-#elif defined (__s390__)
-# define __NR_inotify_init	284
-# define __NR_inotify_add_watch	285
-# define __NR_inotify_rm_watch	286
-#elif defined (__alpha__)
-# define __NR_inotify_init	444
-# define __NR_inotify_add_watch	445
-# define __NR_inotify_rm_watch	446
-#elif defined (__sparc__) || defined (__sparc64__)
-# define __NR_inotify_init	151
-# define __NR_inotify_add_watch	152
-# define __NR_inotify_rm_watch	156
-#elif defined (__arm__)
-# define __NR_inotify_init	316
-# define __NR_inotify_add_watch	317
-# define __NR_inotify_rm_watch	318
-#elif defined (__sh__)
-# define __NR_inotify_init	290
-# define __NR_inotify_add_watch	291
-# define __NR_inotify_rm_watch	292
-#else
-# error "Unsupported architecture!"
-#endif
-
-static inline int inotify_init (void)
-{
-	return syscall (__NR_inotify_init);
-}
-
-static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
-{
-	return syscall (__NR_inotify_add_watch, fd, name, mask);
-}
-
-static inline int inotify_rm_watch (int fd, __u32 wd)
-{
-	return syscall (__NR_inotify_rm_watch, fd, wd);
-}
-
-#endif /* _LINUX_INOTIFY_SYSCALLS_H */
diff --git a/include/inotify.h b/include/inotify.h
deleted file mode 100644
--- a/include/inotify.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Inode based directory notification for Linux
- *
- * Copyright (C) 2005 John McCutchan
- */
-
-#ifndef _LINUX_INOTIFY_H
-#define _LINUX_INOTIFY_H
-
-#include <linux/types.h>
-
-/*
- * struct inotify_event - structure read from the inotify device for each event
- *
- * When you are watching a directory, you will receive the filename for events
- * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
- */
-struct inotify_event {
-	__s32		wd;		/* watch descriptor */
-	__u32		mask;		/* watch mask */
-	__u32		cookie;		/* cookie to synchronize two events */
-	__u32		len;		/* length (including nulls) of name */
-	char		name[0];	/* stub for possible name */
-};
-
-/* the following are legal, implemented events that user-space can watch for */
-#define IN_ACCESS		0x00000001	/* File was accessed */
-#define IN_MODIFY		0x00000002	/* File was modified */
-#define IN_ATTRIB		0x00000004	/* Metadata changed */
-#define IN_CLOSE_WRITE		0x00000008	/* Writtable file was closed */
-#define IN_CLOSE_NOWRITE	0x00000010	/* Unwrittable file closed */
-#define IN_OPEN			0x00000020	/* File was opened */
-#define IN_MOVED_FROM		0x00000040	/* File was moved from X */
-#define IN_MOVED_TO		0x00000080	/* File was moved to Y */
-#define IN_CREATE		0x00000100	/* Subfile was created */
-#define IN_DELETE		0x00000200	/* Subfile was deleted */
-#define IN_DELETE_SELF		0x00000400	/* Self was deleted */
-#define IN_MOVE_SELF		0x00000800	/* Self was moved */
-
-/* the following are legal events.  they are sent as needed to any watch */
-#define IN_UNMOUNT		0x00002000	/* Backing fs was unmounted */
-#define IN_Q_OVERFLOW		0x00004000	/* Event queued overflowed */
-#define IN_IGNORED		0x00008000	/* File was ignored */
-
-/* helper events */
-#define IN_CLOSE		(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
-#define IN_MOVE			(IN_MOVED_FROM | IN_MOVED_TO) /* moves */
-
-/* special flags */
-#define IN_ONLYDIR		0x01000000	/* only watch the path if it is a directory */
-#define IN_DONT_FOLLOW		0x02000000	/* don't follow a sym link */
-#define IN_MASK_ADD		0x20000000	/* add to the mask of an already existing watch */
-#define IN_ISDIR		0x40000000	/* event occurred against dir */
-#define IN_ONESHOT		0x80000000	/* only send event once */
-
-/*
- * All of the events - we build the list by hand so that we can add flags in
- * the future and not break backward compatibility.  Apps will get only the
- * events that they originally wanted.  Be sure to add new events here!
- */
-#define IN_ALL_EVENTS	(IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
-			 IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
-			 IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
-			 IN_MOVE_SELF)
-
-#ifdef __KERNEL__
-
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/config.h>
-
-#ifdef CONFIG_INOTIFY
-
-extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
-				      const char *);
-extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
-					      const char *);
-extern void inotify_unmount_inodes(struct list_head *);
-extern void inotify_inode_is_dead(struct inode *);
-extern u32 inotify_get_cookie(void);
-
-#else
-
-static inline void inotify_inode_queue_event(struct inode *inode,
-					     __u32 mask, __u32 cookie,
-					     const char *filename)
-{
-}
-
-static inline void inotify_dentry_parent_queue_event(struct dentry *dentry,
-						     __u32 mask, __u32 cookie,
-						     const char *filename)
-{
-}
-
-static inline void inotify_unmount_inodes(struct list_head *list)
-{
-}
-
-static inline void inotify_inode_is_dead(struct inode *inode)
-{
-}
-
-static inline u32 inotify_get_cookie(void)
-{
-	return 0;
-}
-
-#endif	/* CONFIG_INOTIFY */
-
-#endif	/* __KERNEL __ */
-
-#endif	/* _LINUX_INOTIFY_H */
diff --git a/src/System/INotify.hsc b/src/System/INotify.hsc
--- a/src/System/INotify.hsc
+++ b/src/System/INotify.hsc
@@ -2,7 +2,7 @@
 -- |
 -- Module      :  System.INotify
 -- Copyright   :  (c) Lennart Kolmodin 2006
--- License     :  GPL
+-- License     :  BSD3
 -- Maintainer  :  kolmodin@dtek.chalmers.se
 -- Stability   :  experimental
 -- Portability :  hc portable, linux only
@@ -21,6 +21,8 @@
 
 module System.INotify
     ( initINotify
+    , killINotify
+    , withINotify
     , addWatch
     , removeWatch
     , INotify
@@ -30,16 +32,16 @@
     , Cookie
     ) where
 
-#include "inotify.h"
+#include "linux/inotify.h"
 
 import Prelude hiding (init)
 import Control.Monad
 import Control.Concurrent
 import Control.Concurrent.MVar
+import Control.Exception (bracket)
 import Data.Maybe
 import Data.Map (Map)
 import qualified Data.Map as Map
-import GHC.Handle
 import Foreign.C
 import Foreign.Marshal
 import Foreign.Ptr
@@ -47,7 +49,13 @@
 import System.Directory
 import System.IO
 import System.IO.Error
+#if __GLASGOW_HASKELL__ >= 612
+import GHC.IO.Handle.FD (fdToHandle')
+import GHC.IO.Device (IODeviceType(Stream))
+#else
+import GHC.Handle
 import System.Posix.Internals
+#endif
 
 import System.INotify.Masks
 
@@ -58,7 +66,7 @@
 type EventMap = Map WD (Event -> IO ())
 type WDEvent = (WD, Event)
 
-data INotify = INotify Handle FD (MVar EventMap)
+data INotify = INotify Handle FD (MVar EventMap) ThreadId ThreadId
 data WatchDescriptor = WatchDescriptor Handle WD deriving Eq
 
 newtype Cookie = Cookie CUInt deriving (Eq,Ord)
@@ -151,7 +159,7 @@
     deriving Eq
 
 instance Show INotify where
-    show (INotify _ fd _) =
+    show (INotify _ fd _ _ _) =
         showString "<inotify fd=" . 
         shows fd $ ">"
 
@@ -164,19 +172,18 @@
 initINotify :: IO INotify
 initINotify = do
     fd <- throwErrnoIfMinus1 "initINotify" c_inotify_init
-    em <- newMVar Map.empty
     let desc = showString "<inotify handle, fd=" . shows fd $ ">"
 #if __GLASGOW_HASKELL__ < 608
     h <-  openFd (fromIntegral fd) (Just Stream) False{-is_socket-} desc ReadMode True{-binary-}
 #else
     h <-  fdToHandle' (fromIntegral fd) (Just Stream) False{-is_socket-} desc ReadMode True{-binary-}
 #endif
-    -- h <- fdToHandle fd
-    inotify_start_thread h em
-    return (INotify h fd em)
+    em <- newMVar Map.empty
+    (tid1, tid2) <- inotify_start_thread h em
+    return (INotify h fd em tid1 tid2)
 
 addWatch :: INotify -> [EventVariety] -> FilePath -> (Event -> IO ()) -> IO WatchDescriptor
-addWatch inotify@(INotify h fd em) masks fp cb = do
+addWatch inotify@(INotify h fd em _ _) masks fp cb = do
     is_dir <- doesDirectoryExist fp
     when (not is_dir) $ do
         file_exist <- doesFileExist fp
@@ -227,20 +234,20 @@
             AllEvents -> inAllEvents
 
 removeWatch :: INotify -> WatchDescriptor -> IO ()
-removeWatch (INotify _ fd _) (WatchDescriptor _ wd) = do
-    throwErrnoIfMinus1 "removeWatch" $
+removeWatch (INotify _ fd _ _ _) (WatchDescriptor _ wd) = do
+    _ <- throwErrnoIfMinus1 "removeWatch" $
       c_inotify_rm_watch (fromIntegral fd) wd
     return ()
 
 rm_watch :: INotify -> WD -> IO ()
-rm_watch (INotify _ _ em) wd =
+rm_watch (INotify _ _ em _ _) wd =
     modifyMVar_ em (return . Map.delete wd)
 
 read_events :: Handle -> IO [WDEvent]
 read_events h = 
     let maxRead = 16385 in
     allocaBytes maxRead $ \buffer -> do
-        hWaitForInput h (-1)  -- wait forever
+        _ <- hWaitForInput h (-1)  -- wait forever
         r <- hGetBufNonBlocking h buffer maxRead
         read_events' buffer r
     where
@@ -283,12 +290,12 @@
         isSet bits = maskIsSet bits mask
         name = fromJust nameM
        
-inotify_start_thread :: Handle -> MVar EventMap -> IO ()
+inotify_start_thread :: Handle -> MVar EventMap -> IO (ThreadId, ThreadId)
 inotify_start_thread h em = do
     chan_events <- newChan
-    forkIO (dispatcher chan_events)
-    forkIO (start_thread chan_events)
-    return ()
+    tid1 <- forkIO (dispatcher chan_events)
+    tid2 <- forkIO (start_thread chan_events)
+    return (tid1,tid2)
     where
     start_thread :: Chan [WDEvent] -> IO ()
     start_thread chan_events = do
@@ -311,6 +318,15 @@
         case handlerM of
           Nothing -> putStrLn "runHandler: couldn't find handler" -- impossible?
           Just handler -> catch (handler event) (\_ -> return ())
+
+killINotify :: INotify -> IO ()
+killINotify (INotify h _ _ tid1 tid2) =
+    do killThread tid1
+       killThread tid2
+       hClose h
+
+withINotify :: (INotify -> IO a) -> IO a
+withINotify = bracket initINotify killINotify
         
 foreign import ccall unsafe "inotify-syscalls.h inotify_init" c_inotify_init :: IO CInt
 foreign import ccall unsafe "inotify-syscalls.h inotify_add_watch" c_inotify_add_watch :: CInt -> CString -> CUInt -> IO CInt
diff --git a/src/System/INotify/Masks.hsc b/src/System/INotify/Masks.hsc
--- a/src/System/INotify/Masks.hsc
+++ b/src/System/INotify/Masks.hsc
@@ -31,7 +31,7 @@
 import Data.Maybe
 import Foreign.C.Types
 
-#include "inotify.h"
+#include "linux/inotify.h"
 
 data Mask
     = UserSpace CUInt
@@ -91,35 +91,3 @@
 #enum Mask, Special, IN_ONESHOT
 
 #enum Mask, All, IN_ALL_EVENTS
-
-{-
-/* the following are legal, implemented events that user-space can watch for */
-#define IN_ACCESS               0x00000001      /* File was accessed */
-#define IN_MODIFY               0x00000002      /* File was modified */
-#define IN_ATTRIB               0x00000004      /* Metadata changed */
-#define IN_CLOSE_WRITE          0x00000008      /* Writtable file was closed */
-#define IN_CLOSE_NOWRITE        0x00000010      /* Unwrittable file closed */
-#define IN_OPEN                 0x00000020      /* File was opened */
-#define IN_MOVED_FROM           0x00000040      /* File was moved from X */
-#define IN_MOVED_TO             0x00000080      /* File was moved to Y */
-#define IN_CREATE               0x00000100      /* Subfile was created */
-#define IN_DELETE               0x00000200      /* Subfile was deleted */
-#define IN_DELETE_SELF          0x00000400      /* Self was deleted */
-#define IN_MOVE_SELF            0x00000800      /* Self was moved */
-
-/* the following are legal events.  they are sent as needed to any watch */
-#define IN_UNMOUNT              0x00002000      /* Backing fs was unmounted */
-#define IN_Q_OVERFLOW           0x00004000      /* Event queued overflowed */
-#define IN_IGNORED              0x00008000      /* File was ignored */
-
-/* helper events */
-#define IN_CLOSE                (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
-#define IN_MOVE                 (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
-
-/* special flags */
-#define IN_ONLYDIR              0x01000000      /* only watch the path if it is a directory */
-#define IN_DONT_FOLLOW          0x02000000      /* don't follow a sym link */
-#define IN_MASK_ADD             0x20000000      /* add to the mask of an already existing w atch */
-#define IN_ISDIR                0x40000000      /* event occurred against dir */
-#define IN_ONESHOT              0x80000000      /* only send event once */
--}
diff --git a/tests/Utils.hs b/tests/Utils.hs
deleted file mode 100644
--- a/tests/Utils.hs
+++ /dev/null
@@ -1,55 +0,0 @@
-module Utils where
-
-import Control.Concurrent.Chan
-import Control.Exception
-
-import System.Directory
-import System.Environment
-import System.Exit
-
-import System.INotify
-
-testName = do
-    n <- getProgName
-    return (n ++ "-playground")
-
-withTempDir f = do
-    path <- testName
-    bracket
-        ( createDirectory path >> return path )
-        ( removeDirectoryRecursive )
-        ( f )
-
-withWatch inot events path action f =
-    bracket
-        ( addWatch inot events path action )
-        ( removeWatch inot )
-        ( const f )
-
-inTestEnviron events action f = do
-    withTempDir $ \testPath -> do
-        inot <- initINotify
-        chan <- newChan
-        withWatch inot events testPath (writeChan chan) $ do
-            action testPath
-            events <- getChanContents chan
-            f events
-
-(~=) :: Eq a => [a] -> [a] -> Bool
-[] ~= _ = True
-(x:xs) ~= (y:ys) = x == y && xs ~= ys
-_ ~= _ = False
-
-asMany :: [a] -> [a] -> [a]
-asMany xs ys = take (length xs) ys
-
-explainFailure expected reality = do
-    putStrLn "Expected:"
-    mapM_ (\x -> putStr "> " >> print x) expected
-    putStrLn "But got:"
-    mapM_ (\x -> putStr "< " >> print x) (asMany expected reality)
-    testFailure
-
-testFailure = exitFailure 
-
-testSuccess = exitWith ExitSuccess
diff --git a/tests/test-all b/tests/test-all
deleted file mode 100644
--- a/tests/test-all
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-
-GHC=ghc
-
-if [[ -n $1 ]]; then
-    GHC="$1"
-    echo Using GHC: $GHC
-fi
-
-TESTS=( `ls test*.hs | cut -d. -f1` )
-
-rm -rf *.o *.hi
-
-for t in ${TESTS[@]}; do
-    rm -rf $t{,.o,.hi}
-    rm -rf $t-playground
-    $GHC -v0 --make $t.hs -o $t
-    echo -n Testing $t ...
-    if [[ -x $t ]]; then
-        ./$t
-        exitCode=$?
-        if [[ $exitCode == 0 ]]; then
-            echo Success
-            rm -rf $t{,.o,.hi}
-        else
-            echo Failure with exit code $exitCode
-        fi
-    else
-        echo Compilation failed
-    fi
-done
diff --git a/tests/test001-list-dir-contents.hs b/tests/test001-list-dir-contents.hs
deleted file mode 100644
--- a/tests/test001-list-dir-contents.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-module Main where
-
-import Control.Monad
-
-import System.Directory
-
-import System.INotify as INotify
-
-import Utils
-
-main =
-    inTestEnviron [Open, Close] getDirectoryContents $ \ events -> do
-        when (expected ~= events)
-            testSuccess
-        explainFailure expected events
-
-expected =
-    [ Opened True Nothing
-    , Closed True Nothing False
-    ]
diff --git a/tests/test002-writefile.hs b/tests/test002-writefile.hs
deleted file mode 100644
--- a/tests/test002-writefile.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-module Main where
-
-import Control.Monad
-
-import System.INotify as INotify
-
-import Utils
-
-write path = do
-    writeFile (path ++ "/hello") ""
-    -- actually writing any contents gives me two Modified
-    
-main =
-    inTestEnviron [AllEvents] write $ \ events -> do
-        when (expected ~= events)
-            testSuccess
-        explainFailure expected events
-
-expected =
-    [ Created   False "hello"
-    , Opened    False (Just "hello")
-    , Modified  False (Just "hello")
-    , Closed    False (Just "hello") True
-    ]
diff --git a/tests/test003-removefile.hs b/tests/test003-removefile.hs
deleted file mode 100644
--- a/tests/test003-removefile.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-module Main where
-
-import Control.Monad
-
-import System.Directory
-
-import System.INotify as INotify
-
-import Utils
-
-file = "hello"
-
-write path = do
-    writeFile (path ++ '/':file) ""
-
-remove path = do
-    removeFile (path ++ '/':file)
-
-action path = do
-    write path
-    remove path
-    
-main =
-    inTestEnviron [AllEvents] action $ \ events -> do
-        when (expected ~= events)
-            testSuccess
-        explainFailure expected events
-
-expected =
-    [ Created   False file
-    , Opened    False (Just file)
-    , Modified  False (Just file)
-    , Closed    False (Just file) True
-    , Deleted   False file
-    ]
diff --git a/tests/test004-modify-file.hs b/tests/test004-modify-file.hs
deleted file mode 100644
--- a/tests/test004-modify-file.hs
+++ /dev/null
@@ -1,47 +0,0 @@
-module Main where
-
-import Control.Exception
-import Control.Monad
-
-import System.Directory
-import System.IO
-
-import System.INotify as INotify
-
-import Utils
-
-file = "hello"
-
-write path = do
-    writeFile (path ++ '/':file) ""
-
-modify path = do
-    bracket
-        (openFile (path ++ '/':file) AppendMode)
-        (hClose)
-        (\h -> hPutStr h "yarr!")
-
-remove path = do
-    removeFile (path ++ '/':file)
-
-action path = do
-    write path
-    modify path
-    remove path
-    
-main =
-    inTestEnviron [AllEvents] action $ \ events -> do
-        when (expected ~= events)
-            testSuccess
-        explainFailure expected events
-
-expected =
-    [ Created   False file
-    , Opened    False (Just file)
-    , Modified  False (Just file)
-    , Closed    False (Just file) True
-    , Opened    False (Just file)
-    , Modified  False (Just file)
-    , Closed    False (Just file) True
-    , Deleted   False file
-    ]
diff --git a/tests/test005-move-file.hs b/tests/test005-move-file.hs
deleted file mode 100644
--- a/tests/test005-move-file.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-module Main where
-
-import Data.Maybe
-
-import Control.Monad
-
-import System.Directory
-import System.IO
-
-import System.INotify as INotify
-
-import Utils
-
-file = "hello"
-file2 = file ++ "2"
-
-write path = do
-    writeFile (path ++ '/':file) ""
-
-move path = do
-    renameFile (path ++ '/':file) (path ++ '/':file2)
-
-remove path = do
-    removeFile (path ++ '/':file2)
-
-action path = do
-    write path
-    move path
-    remove path
-    
-main =
-    inTestEnviron [AllEvents] action $ \ events -> do
-        let cookie = head [ c | MovedOut _ _ c <- events ]
-        when (expected cookie ~= events)
-            testSuccess
-        explainFailure (expected cookie) events
-
-expected cookie =
-    [ Created   False file
-    , Opened    False (Just file)
-    , Modified  False (Just file)
-    , Closed    False (Just file) True
-    , MovedOut  False file  cookie
-    , MovedIn   False file2 cookie
-    , Deleted   False file2
-    ]
