diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # lzlib
 
+## 0.3.0.3
+
+  * Use `bracket` so that memory is freed if an exception is thrown in another
+    thread
+
 ## 0.3.0.2
 
   * Documentation improvements
diff --git a/lzlib.cabal b/lzlib.cabal
--- a/lzlib.cabal
+++ b/lzlib.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.18
 name:               lzlib
-version:            0.3.0.2
+version:            0.3.0.3
 license:            BSD3
 license-file:       LICENSE
 copyright:          Copyright: (c) 2019 Vanessa McHale
diff --git a/src/Codec/Lzip.hs b/src/Codec/Lzip.hs
--- a/src/Codec/Lzip.hs
+++ b/src/Codec/Lzip.hs
@@ -9,6 +9,7 @@
                   ) where
 
 import           Codec.Lzip.Raw
+import           Control.Exception     (bracket)
 import           Control.Monad         (void)
 import           Data.Bits             (shiftL)
 import qualified Data.ByteString       as BS
@@ -63,11 +64,10 @@
         sz = maximum (BS.length <$> bss)
         bufMax = fromIntegral maxSz
 
-    buf <- mallocBytes sz
-    res <- loop decoder bss bufMax (buf, sz) mempty
-
-    void $ lZDecompressClose decoder
-    free buf
+    res <- bracket
+        (mallocBytes sz)
+        ((lZDecompressClose decoder *>) . free)
+        (\buf -> loop decoder bss bufMax (buf, sz) mempty)
 
     pure (BSL.fromChunks res)
 
