diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Revision history for sensu-run
 
+## 0.2.0 -- 2017-07-12
+
+* Relax upper version bound for base
+* Kill child process(es) when timeout occurs
+
 ## 0.1.1.3 -- 2017-06-11
 
 * Relax upper version bound for optparse-applicative
diff --git a/System/Process/Kill.hs b/System/Process/Kill.hs
new file mode 100644
--- /dev/null
+++ b/System/Process/Kill.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE CPP #-}
+module System.Process.Kill (killProcessTree) where
+import System.Process
+
+#if !defined(WINDOWS)
+import System.Process.Internals
+import qualified System.Posix.Signals as Sig
+import qualified System.Posix.Process as Proc
+#endif
+
+-- | Kill all processes in the same process group as the specified process.
+killProcessTree :: ProcessHandle -> IO ()
+killProcessTree ph =
+#if defined(WINDOWS)
+  -- terminateProcess should kill the process and its children.
+  terminateProcess ph
+#else
+  withProcessHandle ph $ \ph_ -> case ph_ of
+    OpenHandle pid -> sendKillSignal pid
+    ClosedHandle {} -> return ()
+#if MIN_VERSION_process(1, 5, 0)
+    OpenExtHandle pid _ _ -> sendKillSignal pid
+#endif
+  where
+    sendKillSignal pid = do
+      pgid <- Proc.getProcessGroupIDOf pid
+      Sig.signalProcessGroup Sig.killProcess pgid
+#endif
diff --git a/sensu-run.cabal b/sensu-run.cabal
--- a/sensu-run.cabal
+++ b/sensu-run.cabal
@@ -1,5 +1,5 @@
 name: sensu-run
-version: 0.1.1.3
+version: 0.2.0
 synopsis: A tool to send command execution results to Sensu
 description:
   @sensu-run@ is a command line tool to send command execution results to Sensu
@@ -23,7 +23,7 @@
   main-is: sensu-run.hs
   build-depends:
       aeson >= 0.11 && < 1.3
-    , base >= 4.9 && < 4.10
+    , base >= 4.9 && < 4.11
     , bytestring >= 0.10 && < 0.11
     , filepath >= 1.4.1 && < 1.5
     , http-client >= 0.5.6 && < 0.6
@@ -37,6 +37,12 @@
     , time >= 1.5.0.1 && < 1.9
     , vector >= 0.11 && < 0.13
     , wreq >= 0.5.0 && < 0.6
-
+  other-modules:
+    Paths_sensu_run
+    System.Process.Kill
+  if os(windows)
+    cpp-options: -DWINDOWS
+  else
+    build-depends: unix
   ghc-options: -Wall -threaded
   default-language: Haskell2010
diff --git a/sensu-run.hs b/sensu-run.hs
--- a/sensu-run.hs
+++ b/sensu-run.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE ApplicativeDo #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DuplicateRecordFields #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiWayIf #-}
@@ -42,6 +43,7 @@
 import qualified Network.Wreq as W
 import qualified Options.Applicative as O
 
+import System.Process.Kill (killProcessTree)
 import qualified Paths_sensu_run as Paths
 
 main :: IO ()
@@ -56,7 +58,10 @@
       executed <- getCurrentTime
       rawStatus <- bracket
         (startProcess cmdspec hdl)
-        terminateProcess
+        (\ph -> do
+          terminateProcess ph
+          killProcessTree ph
+          waitForProcess ph)
         (withTimeout timeout . waitForProcess)
       exited <- getCurrentTime
       rawOutput <- BL.readFile path
@@ -133,20 +138,25 @@
     , std_out = UseHandle hdl
     , std_err = UseHandle hdl
     , close_fds = False
-    , create_group = False
+    , create_group = True -- necessary to not kill sensu-run itself
     , delegate_ctlc = False
     , detach_console = False
     , create_new_console = False
     , new_session = False
     , child_group = Nothing
     , child_user = Nothing
+#if MIN_VERSION_process(1, 5, 0)
+    , use_process_jobs = True
+#endif
     }
   return ph
 
 withTimeout :: Maybe NominalDiffTime -> IO a -> IO (Maybe a)
 withTimeout time io = case time of
-  Just n -> Timeout.timeout (round $ n * 10^(6 :: Int))  io
+  Just n -> Timeout.timeout (seconds n) io
   Nothing -> Just <$> io
+  where
+    seconds n = round $ n * 10 ^ (6 :: Int)
 
 data Options
   = ShowVersion
