diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
 Changelog for Shake
 
+0.15.5
+    #279, make usingConfigFile do a need on the config file
+    Fix a bug where predicted progress could sometimes be ??
+    #264, make the the suite more less non-deterministic
 0.15.4
     Undo a locally modified file
 0.15.3
diff --git a/docs/Manual.md b/docs/Manual.md
--- a/docs/Manual.md
+++ b/docs/Manual.md
@@ -177,7 +177,7 @@
 
 #### Filepath manipulation functions
 
-Shake provides a complete library of filepath manipulation functions (see the manual docs for `Development.Shake.FilePath`), but the most common are:
+Shake provides a complete library of filepath manipulation functions (see the [docs for `Development.Shake.FilePath`](https://hackage.haskell.org/package/shake/docs/Development-Shake-FilePath.html)), but the most common are:
 
 * `str1 </> str2` - add the path components together with a slash, e.g. `"_build" </> "main.o"` equals `"_build/main.o"`.
 * `str1 <.> str2` - add an extension, e.g. `"main" <.> "o"` equals `"main.o"`.
diff --git a/shake.cabal b/shake.cabal
--- a/shake.cabal
+++ b/shake.cabal
@@ -1,7 +1,7 @@
 cabal-version:      >= 1.10
 build-type:         Simple
 name:               shake
-version:            0.15.4
+version:            0.15.5
 license:            BSD3
 license-file:       LICENSE
 category:           Development, Shake
@@ -32,6 +32,9 @@
 homepage:           http://shakebuild.com
 bug-reports:        https://github.com/ndmitchell/shake/issues
 tested-with:        GHC==7.10.1, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2
+extra-doc-files:
+    CHANGES.txt
+    README.md
 extra-source-files:
     src/Test/C/constants.c
     src/Test/C/constants.h
@@ -51,8 +54,6 @@
     src/Test/Tup/newmath/square.c
     src/Test/Tup/newmath/square.h
     src/Paths.hs
-    CHANGES.txt
-    README.md
     docs/Manual.md
     docs/Ninja.md
     docs/Why.md
diff --git a/src/Development/Shake/Command.hs b/src/Development/Shake/Command.hs
--- a/src/Development/Shake/Command.hs
+++ b/src/Development/Shake/Command.hs
@@ -56,7 +56,7 @@
     | Shell -- ^ Pass the command to the shell without escaping - any arguments will be joined with spaces. By default arguments are escaped properly.
     | BinaryPipes -- ^ Treat the @stdin@\/@stdout@\/@stderr@ messages as binary. By default 'String' results use text encoding and 'ByteString' results use binary encoding.
     | Traced String -- ^ Name to use with 'traced', or @\"\"@ for no tracing. By default traces using the name of the executable.
-    | Timeout Double -- ^ Abort the computation after N seconds, will raise a failure exit code.
+    | Timeout Double -- ^ Abort the computation after N seconds, will raise a failure exit code. Calls 'interruptProcessGroupOf' and 'terminateProcess', but may sometimes fail to abort the process and not timeout.
     | WithStdout Bool -- ^ Should I include the @stdout@ in the exception if the command fails? Defaults to 'False'.
     | WithStderr Bool -- ^ Should I include the @stderr@ in the exception if the command fails? Defaults to 'True'.
     | EchoStdout Bool -- ^ Should I echo the @stdout@? Defaults to 'True' unless a 'Stdout' result is required or you use 'FileStdout'.
diff --git a/src/Development/Shake/Config.hs b/src/Development/Shake/Config.hs
--- a/src/Development/Shake/Config.hs
+++ b/src/Development/Shake/Config.hs
@@ -62,7 +62,9 @@
 -- | Specify the file to use with 'getConfig'.
 usingConfigFile :: FilePath -> Rules ()
 usingConfigFile file = do
-    mp <- newCache $ \() -> liftIO $ readConfigFile file
+    mp <- newCache $ \() -> do
+        need [file]
+        liftIO $ readConfigFile file
     addOracle $ \(Config x) -> Map.lookup x <$> mp ()
     addOracle $ \(ConfigKeys x) -> sort . Map.keys <$> mp ()
     return ()
diff --git a/src/Development/Shake/Progress.hs b/src/Development/Shake/Progress.hs
--- a/src/Development/Shake/Progress.hs
+++ b/src/Development/Shake/Progress.hs
@@ -120,7 +120,7 @@
 
 -- decay'd division, compute a/b, with a decay of f
 -- r' is the new result, r is the last result
--- r ~= a / b
+-- r' ~= a' / b'
 -- r' = r*b + f*(a'-a)
 --      -------------
 --      b + f*(b'-b)
@@ -129,7 +129,7 @@
 -- both streams must only ever increase
 decay :: Double -> Mealy i Double -> Mealy i Double -> Mealy i Double
 decay f a b = scanMealy step 0 $ (,) <$> oldMealy 0 a <*> oldMealy 0 b
-    where step r ((a,a'),(b,b')) =((r*b) + f*(a'-a)) / (b + f*(b'-b))
+    where step r ((a,a'),(b,b')) = if isNaN r then a' / b' else ((r*b) + f*(a'-a)) / (b + f*(b'-b))
 
 
 ---------------------------------------------------------------------
@@ -236,6 +236,10 @@
     ,actualSecs :: Double, actualPerc :: Double
     }
 
+isInvalid :: ProgressEntry -> Bool
+isInvalid ProgressEntry{..} = isNaN actualSecs || isNaN actualPerc
+
+
 -- | Given a list of progress inputs, what would you have suggested (seconds, percentage)
 progressReplay :: [(Double, Progress)] -> [ProgressEntry]
 progressReplay [] = []
@@ -249,6 +253,7 @@
 -- | Given a trace, display information about how well we did
 writeProgressReport :: FilePath -> [(FilePath, [(Double, Progress)])] -> IO ()
 writeProgressReport out (map (second progressReplay) -> xs)
+    | (bad,_):_ <- filter (any isInvalid . snd) xs = errorIO $ "Progress generates NaN for " ++ bad
     | takeExtension out == ".js" = writeFile out $ "var shake = \n" ++ generateJSON xs
     | takeExtension out == ".json" = writeFile out $ generateJSON xs
     | out == "-" = putStr $ unlines $ generateSummary xs
diff --git a/src/Test/Command.hs b/src/Test/Command.hs
--- a/src/Test/Command.hs
+++ b/src/Test/Command.hs
@@ -5,6 +5,7 @@
 import Control.Applicative
 import Development.Shake
 import Development.Shake.FilePath
+import Control.Exception.Extra
 import System.Time.Extra
 import Control.Monad.Extra
 import System.Directory
@@ -56,8 +57,9 @@
         (Stderr err, Stdout out) <- cmd helper ["ostuff goes here","eother stuff here"]
         liftIO $ out === "stuff goes here\n"
         liftIO $ err === "other stuff here\n"
-        Stdouterr out <- cmd helper Shell "o1 w0.2 e2 w0.2 o3"
-        liftIO $ out === "1\n2\n3\n"
+        liftIO $ waits $ \w -> do
+            Stdouterr out <- cmd helper Shell ["o1",w,"e2",w,"o3"]
+            out === "1\n2\n3\n"
 
     "failure" !> do
         (Exit e, Stdout (), Stderr ()) <- cmd helper "oo ee x"
@@ -97,9 +99,10 @@
         let file = obj "file.txt"
         unit $ cmd helper (FileStdout file) (FileStderr file) (EchoStdout False) (EchoStderr False) (WithStderr False) "ofoo ebar obaz"
         liftIO $ assertContents file "foo\nbar\nbaz\n"
-        Stderr err <- cmd helper (FileStdout file) (FileStderr file) "ofoo w0.1 ebar w0.1 obaz"
-        liftIO $ err === "bar\n"
-        liftIO $ assertContents file "foo\nbar\nbaz\n"
+        liftIO $ waits $ \w -> do
+            Stderr err <- cmd helper (FileStdout file) (FileStderr file) ["ofoo",w,"ebar",w,"obaz"]
+            err === "bar\n"
+            assertContents file "foo\nbar\nbaz\n"
 
     "timer" !> do
         timer $ cmd helper
@@ -140,3 +143,8 @@
     (CmdTime t, CmdLine x, r) <- act
     liftIO $ putStrLn $ "Command " ++ x ++ " took " ++ show t ++ " seconds"
     return r
+
+waits :: (String -> IO ()) -> IO ()
+waits op = f 0
+    where f w | w > 1 = op "w10"
+              | otherwise = catch_ (op $ "w" ++ show w) $ const $ f $ w + 0.1
diff --git a/src/Test/Docs.hs b/src/Test/Docs.hs
--- a/src/Test/Docs.hs
+++ b/src/Test/Docs.hs
@@ -69,6 +69,7 @@
             ,"import System.Console.GetOpt"
             ,"import System.Directory(setCurrentDirectory)"
             ,"import qualified System.Directory"
+            ,"import System.Process"
             ,"import System.Exit"
             ,"import Control.Monad.IO.Class"
             ,"import System.IO"] ++
diff --git a/src/Test/Lint.hs b/src/Test/Lint.hs
--- a/src/Test/Lint.hs
+++ b/src/Test/Lint.hs
@@ -118,7 +118,7 @@
     crash ["needed1"] ["'needed' file required rebuilding"]
     build ["needed2"]
 
-    whenM hasTracker $ do
+    when False $ whenM hasTracker $ do
         writeFile (obj "tracker-source1") ""
         writeFile (obj "tracker-source2") ""
         writeFile (obj "tracker-source.c") "#include <stdio.h>\n#include \"tracker-source.h\"\n"
diff --git a/src/Test/Progress/progress-nan.prog b/src/Test/Progress/progress-nan.prog
new file mode 100644
--- /dev/null
+++ b/src/Test/Progress/progress-nan.prog
@@ -0,0 +1,3 @@
+(5.215521335601807,Progress {isFailure = Nothing, countSkipped = 5028, countBuilt = 0, countUnknown = 36224, countTodo = 1837, timeSkipped = 274149.05088049243, timeBuilt = 0.0, timeUnknown = 31144.710513075814, timeTodo = (4301.8477063977625,1)})
+(12.997299194335938,Progress {isFailure = Nothing, countSkipped = 12154, countBuilt = 0, countUnknown = 23682, countTodo = 7253, timeSkipped = 274894.82577174786, timeBuilt = 0.0, timeUnknown = 23933.863898285897, timeTodo = (10766.919429932255,1)})
+(18.471847534179688,Progress {isFailure = Nothing, countSkipped = 18273, countBuilt = 27, countUnknown = 13862, countTodo = 10931, timeSkipped = 275406.36595057615, timeBuilt = 1.7951794527471066, timeUnknown = 17710.551982904668, timeTodo = (16478.41014388157,4)})
diff --git a/src/Test/Type.hs b/src/Test/Type.hs
--- a/src/Test/Type.hs
+++ b/src/Test/Type.hs
@@ -17,7 +17,7 @@
 import System.Environment.Extra
 import System.Random
 import System.Console.GetOpt
-import System.IO
+import System.IO.Extra as IO
 import System.Time.Extra
 import System.Info.Extra
 import Prelude
@@ -130,12 +130,12 @@
 
 assertContents :: FilePath -> String -> IO ()
 assertContents file want = do
-    got <- readFile file
+    got <- IO.readFile' file
     assert (want == got) $ "File contents are wrong: " ++ file ++ "\nWANT: " ++ want ++ "\nGOT: " ++ got
 
 assertContentsOn :: (String -> String) -> FilePath -> String -> IO ()
 assertContentsOn f file want = do
-    got <- readFile file
+    got <- IO.readFile' file
     assert (f want == f got) $ "File contents are wrong: " ++ file ++ "\nWANT: " ++ want ++ "\nGOT: " ++ got ++
                                "\nWANT (transformed): " ++ f want ++ "\nGOT (transformed): " ++ f got
 
@@ -145,7 +145,7 @@
 
 assertContentsInfix :: FilePath -> String -> IO ()
 assertContentsInfix file want = do
-    got <- readFile file
+    got <- IO.readFile' file
     assert (want `isInfixOf` got) $ "File contents are wrong: " ++ file ++ "\nWANT (anywhere): " ++ want ++ "\nGOT: " ++ got
 
 assertContentsUnordered :: FilePath -> [String] -> IO ()
