From 3b88faefe7a2a512ebf2dcde4f3cdb3e89b98393 Mon Sep 17 00:00:00 2001 From: Tomas Janousek Date: Sat, 4 Nov 2017 20:07:30 +0100 Subject: Net: fix race condition in netParser/readNetDev/isUp It's possible (and happens) that netParser sees a device that is no longer there when we get to isUp. This happens almost every time I resume from suspend and the WWAN card (USB device) reappears, and results in xmobar showing the exception until I restart it. Originally I tried tryJust (guard . isDoesNotExistError) (B.readFile (operstateDir d)) and it worked for a while but in recent kernels it's possible to open the file and have the device disappear before we get to reading the contents of it, so we need to surround the whole open/read block in catchIOError and make sure it's evaluated. --- src/Plugins/Monitors/Net.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Plugins/Monitors/Net.hs b/src/Plugins/Monitors/Net.hs index e290539..9819fe2 100644 --- a/src/Plugins/Monitors/Net.hs +++ b/src/Plugins/Monitors/Net.hs @@ -27,6 +27,7 @@ import Control.Monad (forM, filterM) import System.Directory (getDirectoryContents, doesFileExist) import System.FilePath (()) import System.Console.GetOpt +import System.IO.Error (catchIOError) import qualified Data.ByteString.Lazy.Char8 as B @@ -105,9 +106,9 @@ existingDevs = getDirectoryContents "/sys/class/net" >>= filterM isDev excludes = [".", "..", "lo"] isUp :: String -> IO Bool -isUp d = do +isUp d = flip catchIOError (const $ return False) $ do operstate <- B.readFile (operstateDir d) - return $ (B.unpack . head . B.lines) operstate `elem` ["up", "unknown"] + return $! (B.unpack . head . B.lines) operstate `elem` ["up", "unknown"] readNetDev :: [String] -> IO NetDevRawTotal readNetDev (d:x:y:_) = do -- cgit v1.2.3