diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,31 @@
 hinotify
 ======
 
-hinotify-0.3.10
----------------
+## 0.4.2
 
+* Depend on libinotify on NetBSD (https://github.com/haskell-fswatch/hinotify/pull/35)
+* Fix for GHC 9.10 (https://github.com/haskell-fswatch/hinotify/pull/39)
+* Switch maintainer to thomasjm
+* Switch to GitHub Actions CI to test both Cabal and Stack builds
+* Start testing Ubuntu ARM in CI
+
+## 0.4.1
+
+* Depend on inotify library on {Free,Open}BSD
+
+## 0.4
+
+* Allow async-2.*
+
+## 0.3.10
+
 - Allow async-2.2.
 - Use `RawFilePath` (`ByteString`) for filenames, from `unix` package.
 
   Changes the `Event` type and `addWatch` function.
 
 
-hinotify-0.3.9
---------------
+## 0.3.9
 
 Patches contributed by Simon Marlow marlowsd@gmail.com
 
@@ -27,8 +41,7 @@
 
   https://github.com/kolmodin/hinotify/pull/23
 
-hinotify-0.3.8
---------------
+## 0.3.8
 
 - Use file system encoding for file names.
 
@@ -39,3 +52,41 @@
   Fixes https://github.com/kolmodin/hinotify/issues/13
 
   Patch contributed by Joey Hess joeyh@joeyh.name
+
+## 0.3.7
+
+* Bug fix: When registerering a new watch on a path which is already watched,
+  don't overwrite the event listener from the previous watch.
+
+## 0.3.2
+
+* Make each `WatchDescriptor` contain its `INotify`. Changes to the function types:
+
+>      -removeWatch :: INotify -> WatchDescriptor -> IO ()
+>      +removeWatch :: WatchDescriptor -> IO ()
+
+* Fix typo in declaration of `Deleted` in `data Event`;
+
+>      - { isDirecotry :: Bool
+>      + { isDirectory :: Bool
+
+## 0.3.1
+
+* Use `inotify.h` from `glibc` rather than from the linux headers, as
+      recommended upstream.
+
+## 0.3
+
+* Compiles with GHC 6.12, GHC 6.10.4, GHC 6.8.2 and GHC 6.6.1
+
+## 0.2
+
+* Updates to the API
+    - Function names is now in semiCamelCase
+    - Restructure event parameters to make it more consistent
+* Small test suit in `tests/`
+* Compiles with GHC 6.8.2 and GHC 6.6.1
+* Requires Cabal 1.2
+
+## 0.1
+* Initial release
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,64 +1,19 @@
 hinotify: inotify for Haskell
 =============================
 
-[![Build Status](https://api.travis-ci.org/kolmodin/hinotify.png?branch=master)](http://travis-ci.org/kolmodin/hinotify)
+[![CI](https://github.com/haskell-fswatch/hinotify/actions/workflows/ci.yml/badge.svg)](https://github.com/haskell-fswatch/hinotify/actions/workflows/ci.yml)
 
 About
 -----
 
-hinotify, a library to [inotify] 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.
-
-This module is named `hinotify`.
-
-See example code in the `examples` directory, distributed with the source
-code.
+This package provides bindings to [inotify](http://www.kernel.org/pub/linux/kernel/people/rml/inotify/), which has been part of the Linux kernel since 2.6.13.
 
-[inotify]: http://www.kernel.org/pub/linux/kernel/people/rml/inotify/
+The `inotify` subsystem provides file system event notifications. Simply add a watcher to a file or directory and you get events when it is accessed, modified, etc.
 
 News
 ----
 
-**hinotify 0.3.7**
-
-* Bug fix: When registerering a new watch on a path which is already watched,
-  don't overwrite the event listener from the previous watch.
-
-**hinotify 0.3.2**
-
-* Make each `WatchDescriptor` contain its `INotify`. Changes to the function types:
-
->      -removeWatch :: INotify -> WatchDescriptor -> IO ()
->      +removeWatch :: WatchDescriptor -> IO ()
-
-* Fix typo in declaration of `Deleted` in `data Event`;
-
->      - { isDirecotry :: Bool
->      + { isDirectory :: Bool
-
-**hinotify 0.3.1**
-
-* Use `inotify.h` from `glibc` rather than from the linux headers, as
-      recommended upstream.
-
-**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
-    - Function names is now in semiCamelCase
-    - Restructure event parameters to make it more consistent
-* Small test suit in `tests/`
-* Compiles with GHC 6.8.2 and GHC 6.6.1
-* Requires Cabal 1.2
-
-**hinotify 0.1**
-:   Initial release
+See [CHANGELOG.md](./CHANGELOG.md).
 
 API
 ---
@@ -67,49 +22,17 @@
 
 ```haskell
 initINotify :: IO INotify
+
 addWatch :: INotify
          -> [EventVariety]   -- different events to listen on
-         -> FilePath         -- file/directory to watch
-         -> (Event -> IO ()) -- event handler
+         -> RawFilePath      -- file/directory to watch
+         -> (Event -> IO ()) -- event handler callback
          -> IO WatchDescriptor
-removeWatch :: WatchDescriptor -> IO ()
-```
 
-A sample program:
-
-```haskell
-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 wd
+removeWatch :: WatchDescriptor -> IO ()
 ```
 
-Download
---------
-
-The code is available via the [homepage], and via darcs:
-
-    git clone https://github.com/kolmodin/hinotify.git
-
-The [API] is available online.
-
-I'm most grateful for feedback on the API, and what else you might have to
-suggest.
+See this [example](./examples/simple/simple.hs) or the [docs](https://hackage.haskell.org/package/hinotify/docs/System-INotify.html).
 
 Author
 ------
@@ -121,11 +44,6 @@
 Legal
 -----
 
-This software is released under a BSD-style license. See LICENSE for
-more details.
+This software is released under a BSD-style license. See LICENSE for more details.
 
 Copyright &copy; 2007-2012 Lennart Kolmodin
-
-[homepage]: https://github.com/kolmodin/hinotify.git
-
-[API]: http://hackage.haskell.org/packages/archive/hinotify/latest/doc/html/System-INotify.html
diff --git a/hinotify.cabal b/hinotify.cabal
--- a/hinotify.cabal
+++ b/hinotify.cabal
@@ -1,5 +1,5 @@
 name:               hinotify
-version:            0.3.10
+version:            0.4.2
 build-type:         Simple
 synopsis:           Haskell binding to inotify
 description:
@@ -7,11 +7,12 @@
     allowing applications to subscribe to notifications when a file is
     accessed or modified.
 category:           System
-homepage:           https://github.com/kolmodin/hinotify.git
+homepage:           https://github.com/kolmodin/hinotify
+bug-reports:        https://github.com/kolmodin/hinotify/issues
 license:            BSD3
 license-file:       LICENSE
 author:             Lennart Kolmodin
-maintainer:         Lennart Kolmodin <kolmodin@gmail.com>
+maintainer:         Tom McLaughlin <tom@codedown.io>
 extra-source-files: README.md, CHANGELOG.md
 cabal-version:      >= 1.10
 
@@ -22,7 +23,7 @@
 library
     default-language: Haskell2010
     build-depends:  base >= 4.5.0.0 && < 5, bytestring, containers, unix,
-                    async >= 1.0 && < 2.3
+                    async == 2.*
 
     exposed-modules:
         System.INotify
@@ -32,6 +33,9 @@
     ghc-options: -Wall
     includes: sys/inotify.h
     hs-source-dirs: src
+
+    if os(freebsd) || os(netbsd) || os(openbsd)
+      extra-libraries: inotify
 
 test-suite test001
     type: exitcode-stdio-1.0
diff --git a/src/System/INotify.hsc b/src/System/INotify.hsc
--- a/src/System/INotify.hsc
+++ b/src/System/INotify.hsc
@@ -35,30 +35,29 @@
 
 #include "sys/inotify.h"
 
-import Prelude hiding (init)
-import Control.Monad
 import Control.Concurrent
 import Control.Concurrent.Async
 import Control.Exception as E hiding (mask)
-import Data.Maybe
+import Control.Monad
+import Data.Bits ((.|.))
 import Data.Map (Map)
 import qualified Data.Map as Map
+import Data.Maybe
 import Foreign.C
 import Foreign.Marshal hiding (void)
 import Foreign.Ptr
 import Foreign.Storable
+import GHC.IO.Device (IODeviceType(Stream))
+import GHC.IO.FD as FD (mkFD)
+import GHC.IO.Handle (mkFileHandle)
+import Prelude hiding (init)
+import System.INotify.Masks
 import System.IO
 import System.IO.Error
-
 import System.Posix.ByteString.FilePath
 import System.Posix.Files.ByteString
 
-import GHC.IO.FD as FD (mkFD)
-import GHC.IO.Handle.FD (mkHandleFromFD)
-import GHC.IO.Device (IODeviceType(Stream))
 
-import System.INotify.Masks
-
 type FD = CInt
 type WD = CInt
 type Masks = CUInt
@@ -174,16 +173,18 @@
 
 initINotify :: IO INotify
 initINotify = do
-    fdint <- throwErrnoIfMinus1 "initINotify" c_inotify_init
-    (fd,fd_type) <- FD.mkFD fdint ReadMode (Just (Stream,0,0))
-            False{-is_socket-}
-            False{-is_nonblock-}
-    h <- mkHandleFromFD fd fd_type
-           (showString "<inotify handle, fd=" . shows fd $ ">")
-           ReadMode
-           True  -- make non-blocking.  Otherwise reading uses select(), which
-                 -- can fail when there are >=1024 FDs
-           Nothing -- no encoding, so binary
+    fdint <- throwErrnoIfMinus1 "initINotify" $ c_inotify_init1 (c_IN_NONBLOCK .|. c_IN_CLOEXEC)
+    (fd, _) <- FD.mkFD fdint ReadMode (Just (Stream,0,0))
+        False -- is_socket
+        True  -- make non-blocking.  Otherwise reading uses select(), which can fail when there are >=1024 FDs
+
+    h <- mkFileHandle
+        fd
+        (showString "<inotify handle, fd=" . shows fd $ ">")
+        ReadMode
+        Nothing -- no encoding, so binary
+        noNewlineTranslation
+
     em <- newMVar Map.empty
     (tid1, tid2) <- inotify_start_thread h em
     return (INotify h fdint em tid1 tid2)
@@ -359,6 +360,12 @@
 withINotify :: (INotify -> IO a) -> IO a
 withINotify = bracket initINotify killINotify
 
-foreign import ccall unsafe "sys/inotify.h inotify_init" c_inotify_init :: IO CInt
+c_IN_NONBLOCK :: CInt
+c_IN_NONBLOCK = #const IN_NONBLOCK
+
+c_IN_CLOEXEC :: CInt
+c_IN_CLOEXEC = #const IN_CLOEXEC
+
+foreign import ccall unsafe "sys/inotify.h inotify_init1" c_inotify_init1 :: CInt -> IO CInt
 foreign import ccall unsafe "sys/inotify.h inotify_add_watch" c_inotify_add_watch :: CInt -> CString -> CUInt -> IO CInt
 foreign import ccall unsafe "sys/inotify.h inotify_rm_watch" c_inotify_rm_watch :: CInt -> CInt -> IO CInt
