diff --git a/process-extras.cabal b/process-extras.cabal
--- a/process-extras.cabal
+++ b/process-extras.cabal
@@ -1,5 +1,5 @@
 Name:               process-extras
-Version:            0.3.3.8
+Version:            0.3.4
 Synopsis:           Process extras
 Description:        Extends <http://hackage.haskell.org/package/process>.
                     Read process input and output as ByteStrings or
diff --git a/src/System/Process/Common.hs b/src/System/Process/Common.hs
--- a/src/System/Process/Common.hs
+++ b/src/System/Process/Common.hs
@@ -1,15 +1,17 @@
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE FunctionalDependencies #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module System.Process.Common
     ( ProcessMaker(process)
     , ListLikeProcessIO(forceOutput, readChunks)
-    , ProcessOutput(pidf, outf, errf, intf, codef)
+    , ProcessOutput(ProcessInput, pidf, outf, errf, intf, codef)
     , readProcessWithExitCode
     , readCreateProcessWithExitCode
     , readCreateProcess
@@ -20,7 +22,7 @@
 import Control.DeepSeq (NFData)
 import Control.Exception as E (SomeException, onException, catch, mask, throw, try)
 import Control.Monad
-import Data.ListLike (null)
+import Data.ListLike as ListLike (null)
 import Data.ListLike.IO (ListLikeIO, hGetContents, hPutStr)
 import Data.Monoid ((<>))
 import Generics.Deriving.Instances ()
@@ -63,14 +65,16 @@
       hSetBuffering errh errmode
       return (inh, outh, errh, pid)
 
-class Monoid b => ProcessOutput a b | b -> a where
-    pidf :: ProcessHandle -> b
-    outf :: a -> b
-    errf :: a -> b
-    intf :: SomeException -> b
-    codef :: ExitCode -> b
+class Monoid (ProcessInput a) => ProcessOutput a where
+    type ProcessInput a
+    pidf :: ProcessHandle -> a
+    outf :: ProcessInput a -> a
+    errf :: ProcessInput a -> a
+    intf :: SomeException -> a
+    codef :: ExitCode -> a
 
-instance ListLikeProcessIO a c => ProcessOutput a (ExitCode, a, a) where
+instance ListLikeProcessIO a c => ProcessOutput (ExitCode, a, a) where
+    type ProcessInput (ExitCode, a, a) = a
     pidf _ = mempty
     codef c = (c, mempty, mempty)
     outf x = (mempty, x, mempty)
@@ -105,7 +109,7 @@
     -> IO (ExitCode, a, a) -- ^ exitcode, stdout, stderr
 readCreateProcessWithExitCode = readCreateProcess
 
-readCreateProcess :: (ProcessMaker maker, ProcessOutput a b, ListLikeProcessIO a c) => maker -> a -> IO b
+readCreateProcess :: (ProcessMaker maker, ProcessOutput b, ListLikeProcessIO (ProcessInput b) c) => maker -> ProcessInput b -> IO b
 readCreateProcess maker input = mask $ \restore -> do
     (inh, outh, errh, pid) <- process maker
     flip onException
@@ -118,9 +122,14 @@
       -- fork off a thread to start consuming stderr
       waitErr <- forkWait $ errf <$> (hGetContents errh >>= forceOutput)
 
-      -- now write and flush any input
-      unless (null input) $ do ignoreResourceVanished (hPutStr inh input); hFlush inh
-      hClose inh -- done with stdin
+      -- now write and flush any input.  Catch and ignore
+      -- ResourceVanished to avoid crashes when the process we are
+      -- writing to exits prematurely.
+      ignoreResourceVanished $ do
+        unless (ListLike.null input) $ do
+          hPutStr inh input
+          hFlush inh
+        hClose inh -- stdin has been fully written
 
       -- wait on the output
       out <- waitOut
@@ -142,7 +151,7 @@
       ignoreResourceVanished' e = throw e
 
 -- | Like readCreateProcess, but the output is read lazily.
-readCreateProcessLazy :: (ProcessMaker maker, ProcessOutput a b, ListLikeProcessIO a c) => maker -> a -> IO b
+readCreateProcessLazy :: (ProcessMaker maker, ProcessOutput b, ListLikeProcessIO (ProcessInput b) c) => maker -> ProcessInput b -> IO b
 readCreateProcessLazy maker input = mask $ \restore -> do
     (inh, outh, errh, pid) <- process maker
     onException
@@ -158,19 +167,19 @@
           waitForProcess pid)
 
 -- | Helper function for readCreateProcessLazy.
-readInterleaved :: (ListLikeProcessIO a c, ProcessOutput a b) =>
-                   [(a -> b, Handle)] -> IO b -> IO b
+readInterleaved :: (ListLikeProcessIO (ProcessInput b) c, ProcessOutput b) =>
+                   [(ProcessInput b -> b, Handle)] -> IO b -> IO b
 readInterleaved pairs finish = newEmptyMVar >>= readInterleaved' pairs finish
 
-readInterleaved' :: forall a b c. (ListLikeProcessIO a c, ProcessOutput a b) =>
-                    [(a -> b, Handle)] -> IO b -> MVar (Either Handle b) -> IO b
+readInterleaved' :: forall b c. (ListLikeProcessIO (ProcessInput b) c, ProcessOutput b) =>
+                    [(ProcessInput b -> b, Handle)] -> IO b -> MVar (Either Handle b) -> IO b
 readInterleaved' pairs finish res = do
   mapM_ (forkIO . uncurry readHandle) pairs
   takeChunks (length pairs)
     where
       -- Forked thread to read the input and send it to takeChunks via
       -- the MVar.
-      readHandle :: (a -> b) -> Handle -> IO ()
+      readHandle :: (ProcessInput b -> b) -> Handle -> IO ()
       readHandle f h = do
         cs <- readChunks h
         -- If the type returned as stdout and stderr is lazy we need
