diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,27 @@
+# 1.1.0 (2018-10-12)
+
+ * Work around changes in exceptions-0.10.0.  This version should
+   compile cleanly and work with ghc-8.6.1.
+
+# 1.0.4 (2018-09-02)
+
+ * bugfix: memory leak in BGZF encoder
+
+# 1.0.3 (2018-08-26)
+
+ * bugfix: seeking had been broken for a while
+ 
+# 1.0.2 (2018-07-08)
+
+ * compatibility with ghc-8.4.1
+ * bugfix: long headers were garbled when writing BAM files
+ * more robust imports to avoid breakage when dependencies update
+ 
+# 1.0.1 (2018-02-06)
+
+ * Bugfix: merging of overlapping read pairs
+
+# 1.0.0 (2018-01-28)
+
+ * Removed dead code and failed experiments.  `biohazard` is now feature
+   complete by decree.
diff --git a/biohazard.cabal b/biohazard.cabal
--- a/biohazard.cabal
+++ b/biohazard.cabal
@@ -1,5 +1,5 @@
 Name:                biohazard
-Version:             1.0.4
+Version:             1.1.0
 Synopsis:            bioinformatics support library
 Description:         This is a collection of modules I separated from
                      various bioinformatics tools.
@@ -8,6 +8,7 @@
 Homepage:            https://bitbucket.org/ustenzel/biohazard
 License:             BSD3
 License-File:        LICENSE
+Extra-Source-Files:  CHANGELOG.md
 
 Author:              Udo Stenzel
 Maintainer:          u.stenzel@web.de
@@ -15,7 +16,7 @@
 
 Cabal-version:       >= 1.10
 Build-type:          Simple
-Tested-with:         GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1, GHC == 8.4.1, GHC == 8.4.3
+Tested-with:         GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1, GHC == 8.4.3, GHC == 8.6.1
 
 source-repository head
   type:     git
@@ -57,14 +58,14 @@
 
   Build-depends:       async                    >= 2.0 && < 2.3,
                        attoparsec               >= 0.10 && < 0.14,
-                       base                     >= 4.7 && < 4.12,
+                       base                     >= 4.7 && < 4.13,
                        base-prelude             == 1.2.0.*,
                        bytestring               >= 0.10.2 && < 0.11,
-                       containers               == 0.5.*,
-                       exceptions               >= 0.6 && < 0.9,
+                       containers               >= 0.5 && < 0.7,
+                       exceptions               >= 0.6 && < 0.11,
                        hashable                 >= 1.0 && < 1.3,
                        primitive                >= 0.5 && < 0.7,
-                       stm                      == 2.4.*,
+                       stm                      >= 2.4 && < 2.6,
                        text                     >= 1.0 && < 1.3,
                        transformers             >= 0.4.1 && < 0.6,
                        unix                     >= 2.5 && < 2.8,
diff --git a/src/Bio/Bam/Reader.hs b/src/Bio/Bam/Reader.hs
--- a/src/Bio/Bam/Reader.hs
+++ b/src/Bio/Bam/Reader.hs
@@ -78,7 +78,7 @@
 decodeAnyBamOrSam :: MonadIO m => BamEnumeratee m a
 decodeAnyBamOrSam it = isBamOrSam >>= \k -> k it
 
-decodeAnyBamOrSamFile :: (MonadIO m, MonadMask m)
+decodeAnyBamOrSamFile :: MonadBracketIO m
                       => FilePath -> (BamMeta -> Iteratee [BamRec] m a) -> m (Iteratee [BamRec] m a)
 decodeAnyBamOrSamFile fn k = enumFileRandom defaultBufSize fn (decodeAnyBamOrSam k) >>= run
 
@@ -207,13 +207,13 @@
 decodeAnyBam it = do mk <- isBam ; case mk of Just  k -> k it
                                               Nothing -> fail "this isn't BAM."
 
-decodeAnyBamFile :: (MonadIO m, MonadMask m) => FilePath -> (BamMeta -> Iteratee [BamRaw] m a) -> m (Iteratee [BamRaw] m a)
+decodeAnyBamFile :: MonadBracketIO m => FilePath -> (BamMeta -> Iteratee [BamRaw] m a) -> m (Iteratee [BamRaw] m a)
 decodeAnyBamFile fn k = enumFileRandom defaultBufSize fn (decodeAnyBam k) >>= run
 
-concatDefaultInputs :: (MonadIO m, MonadMask m) => Enumerator' BamMeta [BamRaw] m a
+concatDefaultInputs :: MonadBracketIO m => Enumerator' BamMeta [BamRaw] m a
 concatDefaultInputs it0 = liftIO getArgs >>= \fs -> concatInputs fs it0
 
-concatInputs :: (MonadIO m, MonadMask m) => [FilePath] -> Enumerator' BamMeta [BamRaw] m a
+concatInputs :: MonadBracketIO m => [FilePath] -> Enumerator' BamMeta [BamRaw] m a
 concatInputs [       ] = enumFd defaultBufSize stdInput . decodeAnyBam >=> run
 concatInputs (fp0:fps) = enum1 fp0 >=> go fps
   where
@@ -221,12 +221,12 @@
     enum1 "-" = enumFd   defaultBufSize stdInput . decodeAnyBam >=> run
     enum1  fp = enumFile defaultBufSize fp       . decodeAnyBam >=> run
 
-mergeDefaultInputs :: (MonadIO m, MonadMask m)
+mergeDefaultInputs :: MonadBracketIO m
     => (BamMeta -> Enumeratee [BamRaw] [BamRaw] (Iteratee [BamRaw] m) a)
     -> Enumerator' BamMeta [BamRaw] m a
 mergeDefaultInputs (?) it0 = liftIO getArgs >>= \fs -> mergeInputs (?) fs it0
 
-mergeInputs :: (MonadIO m, MonadMask m)
+mergeInputs :: MonadBracketIO m
     => (BamMeta -> Enumeratee [BamRaw] [BamRaw] (Iteratee [BamRaw] m) a)
     -> [FilePath] -> Enumerator' BamMeta [BamRaw] m a
 mergeInputs  _  [        ] = \k -> enumFd defaultBufSize stdInput (decodeAnyBam k) >>= run
diff --git a/src/Bio/Bam/Writer.hs b/src/Bio/Bam/Writer.hs
--- a/src/Bio/Bam/Writer.hs
+++ b/src/Bio/Bam/Writer.hs
@@ -24,7 +24,6 @@
 import Foreign.Marshal.Alloc        ( alloca )
 import System.IO                    ( openBinaryFile, IOMode(..) )
 
-import qualified Control.Monad.Catch                as C
 import qualified Data.ByteString                    as B
 import qualified Data.ByteString.Char8              as S
 import qualified Data.Vector.Generic                as V
@@ -119,8 +118,8 @@
 -- | Writes BAM encoded stuff to a file.
 writeBamFile :: IsBamRec r => FilePath -> BamMeta -> Iteratee [r] IO ()
 writeBamFile fp meta =
-    C.bracket (liftIO $ openBinaryFile fp WriteMode)
-              (liftIO . hClose)
+    bracketIO (openBinaryFile fp WriteMode)
+              (hClose)
               (flip writeBamHandle meta)
 
 -- | write BAM encoded stuff to stdout
diff --git a/src/Bio/Iteratee.hs b/src/Bio/Iteratee.hs
--- a/src/Bio/Iteratee.hs
+++ b/src/Bio/Iteratee.hs
@@ -121,13 +121,13 @@
 type Enumerator' h eo m b = (h -> Iteratee eo m b) -> m (Iteratee eo m b)
 type Enumeratee' h ei eo m b = (h -> Iteratee eo m b) -> Iteratee ei m (Iteratee eo m b)
 
-enumAuxFile :: (MonadIO m, MonadMask m) => FilePath -> Iteratee S.ByteString m a -> m a
+enumAuxFile :: MonadBracketIO m => FilePath -> Iteratee S.ByteString m a -> m a
 enumAuxFile fp it = liftIO (findAuxFile fp) >>= \f -> enumFile defaultBufSize f it >>= run
 
-enumDefaultInputs :: (MonadIO m, MonadMask m) => Enumerator S.ByteString m a
+enumDefaultInputs :: MonadBracketIO m => Enumerator S.ByteString m a
 enumDefaultInputs it0 = liftIO getArgs >>= flip enumInputs it0
 
-enumInputs :: (MonadIO m, MonadMask m) => [FilePath] -> Enumerator S.ByteString m a
+enumInputs :: MonadBracketIO m => [FilePath] -> Enumerator S.ByteString m a
 enumInputs [] = enumFd defaultBufSize stdInput
 enumInputs xs = go xs
   where go ("-":fs) = enumFd defaultBufSize stdInput >=> go fs
diff --git a/src/Bio/Iteratee/Base.hs b/src/Bio/Iteratee/Base.hs
--- a/src/Bio/Iteratee/Base.hs
+++ b/src/Bio/Iteratee/Base.hs
@@ -169,24 +169,16 @@
 
 
 instance NullPoint s => MonadTrans (Iteratee s) where
-  lift m = Iteratee $ \onDone _ -> m >>= flip onDone (Chunk emptyP)
+    lift m = Iteratee $ \onDone _ -> m >>= flip onDone (Chunk emptyP)
 
 instance (MonadIO m, Nullable s, NullPoint s) => MonadIO (Iteratee s m) where
-  liftIO = lift . liftIO
+    liftIO = lift . liftIO
 
-instance (MonadThrow m, Nullable s, NullPoint s) =>
-  MonadThrow (Iteratee s m) where
+instance (MonadThrow m, Nullable s, NullPoint s) => MonadThrow (Iteratee s m) where
     throwM e    = lift $ CIO.throwM e
 
-instance (MonadCatch m, Nullable s, NullPoint s) =>
-  MonadCatch (Iteratee s m) where
+instance (MonadCatch m, Nullable s, NullPoint s) => MonadCatch (Iteratee s m) where
     m `catch` f = Iteratee $ \od oc -> runIter m od oc `CIO.catch` (\e -> runIter (f e) od oc)
-
--- prior to exceptions-0.6, these were part of MonadCatch
-instance (MonadMask m, Nullable s, NullPoint s) => MonadMask (Iteratee s m) where
-    mask q      = Iteratee $ \od oc -> CIO.mask $ \u -> runIter (q $ ilift u) od oc
-    uninterruptibleMask q = Iteratee $ \od oc -> CIO.uninterruptibleMask $ \u -> runIter (q $ ilift u) od oc
-
 
 -- |Send 'EOF' to the @Iteratee@ and disregard the unconsumed part of the
 -- stream.  If the iteratee is in an exception state, that exception is
diff --git a/src/Bio/Iteratee/IO.hs b/src/Bio/Iteratee/IO.hs
--- a/src/Bio/Iteratee/IO.hs
+++ b/src/Bio/Iteratee/IO.hs
@@ -15,10 +15,9 @@
 where
 
 import Bio.Iteratee.Iteratee
-import Bio.Prelude hiding ( bracket, loop )
-import Control.Monad.Catch ( MonadMask, bracket )
-import Control.Monad.IO.Class ( MonadIO(..) )
-import System.IO (SeekMode(..))
+import Bio.Prelude       hiding ( bracket, loop )
+import Control.Monad.IO.Class   ( MonadIO(..)   )
+import System.IO                ( SeekMode(..)  )
 
 import qualified Data.ByteString as B
 
@@ -65,25 +64,25 @@
 
 
 
-enumFile' :: (MonadIO m, MonadMask m) =>
+enumFile' :: MonadBracketIO m =>
   (Int -> Fd -> Enumerator s m a)
   -> Int -- ^Buffer size
   -> FilePath
   -> Enumerator s m a
-enumFile' enumf bufsize filepath iter = bracket
-  (liftIO $ openFd filepath ReadOnly Nothing defaultFileFlags)
-  (liftIO . closeFd)
+enumFile' enumf bufsize filepath iter = bracketIO
+  (openFd filepath ReadOnly Nothing defaultFileFlags)
+  (closeFd)
   (flip (enumf bufsize) iter)
 
 enumFile ::
-  (MonadIO m, MonadMask m)
+  MonadBracketIO m
   => Int                 -- ^Buffer size
   -> FilePath
   -> Enumerator Bytes m a
 enumFile = enumFile' enumFd
 
 enumFileRandom ::
-  (MonadIO m, MonadMask m)
+  MonadBracketIO m
   => Int                 -- ^Buffer size
   -> FilePath
   -> Enumerator Bytes m a
diff --git a/src/Bio/Iteratee/Iteratee.hs b/src/Bio/Iteratee/Iteratee.hs
--- a/src/Bio/Iteratee/Iteratee.hs
+++ b/src/Bio/Iteratee/Iteratee.hs
@@ -18,6 +18,7 @@
   ,mBind_
   ,ioBind
   ,ioBind_
+  ,MonadBracketIO(..)
   -- ** Chunkwise Iteratees
   ,mapChunksM_
   ,foldChunksM
@@ -63,6 +64,7 @@
 
 import Bio.Iteratee.Base
 import Bio.Prelude hiding (loop)
+import Control.Monad.Catch as CIO
 import Control.Monad.IO.Class (MonadIO(..))
 import Control.Monad.Trans.Class (MonadTrans(..))
 
@@ -285,6 +287,24 @@
 infixl 1 `ioBind_`
 ioBind_ :: MonadIO m => IO a -> Iteratee s m b -> Iteratee s m b
 ioBind_ m b = Iteratee $ \onDone onCont -> liftIO m >> runIter b onDone onCont
+
+-- | Runs an 'Iteratee' in between an 'IO' action to acquire a resource
+-- and one to release it.  'Iteratee' can't be an instance of
+-- 'CIO.MonadMask', so 'CIO.bracket' isn't defined for it.  However, if
+-- we restrict the acquire/release actions to 'IO', which is the most
+-- important use case anyway, we can directly implement this weaker
+-- version.
+class MonadIO m => MonadBracketIO m where
+    bracketIO :: IO a -> (a -> IO b) -> (a -> m c) -> m c
+
+instance MonadBracketIO IO where
+    {-# INLINE bracketIO #-}
+    bracketIO = CIO.bracket
+
+instance (MonadBracketIO m, Nullable s) => MonadBracketIO (Iteratee s m) where
+    {-# INLINE bracketIO #-}
+    bracketIO acquire release use =
+        Iteratee $ \od oc -> bracketIO acquire release (\h -> runIter (use h) od oc)
 
 -- | Convert one stream into another with the supplied mapping function.
 -- This function operates on whole chunks at a time, contrasting to
