File remove-state-file-after-startup.patch of Package xmonad
From 89a8cc88c31163dd35d3182bbba7cdd0630ff54b Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@devalot.com>
Date: Thu, 30 Mar 2017 13:42:16 -0700
Subject: [PATCH] Remove the xmonad state file after reading it
Tries to make sure IO is not lazy so the file is processed before it
is removed from the file system.
Fixes #86 and friends.
---
CHANGES.md | 14 ++++++++++++++
src/XMonad/Operations.hs | 16 +++++++++++++---
2 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index fed3bc9..ebb104f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,19 @@
# Change Log / Release Notes
+## 0.14 (Not Yet Released)
+
+### Bug Fixes
+
+ * The state file that xmonad uses while restarting itself is now
+ removed after it is processed. This fixes a bug that manifested
+ in several different ways:
+
+ - Names of old workspaces would be resurrected after a restart
+ - Screen sizes would be wrong after changing monitor configuration (#90)
+ - `spawnOnce` stopped working (xmonad/xmonad-contrib#155)
+ - Focus did not follow when moving between workspaces (#87)
+ - etc.
+
## 0.13 (February 10, 2017)
### Breaking Changes
diff --git a/src/XMonad/Operations.hs b/src/XMonad/Operations.hs
index 4b46571..7dbb45c 100644
--- a/src/XMonad/Operations.hs
+++ b/src/XMonad/Operations.hs
@@ -465,14 +465,21 @@ writeStateToFile = do
catchIO (writeFile path $ show stateData)
-- | Read the state of a previous xmonad instance from a file and
--- return that state.
+-- return that state. The state file is removed after reading it.
readStateFile :: (LayoutClass l Window, Read (l Window)) => XConfig l -> X (Maybe XState)
readStateFile xmc = do
path <- stateFileName
- raw <- userCode $ io (readFile path)
+
+ -- I'm trying really hard here to make sure we read the entire
+ -- contents of the file before it is removed from the file system.
+ sf' <- userCode . io $ do
+ raw <- withFile path ReadMode readStrict
+ return $! maybeRead reads raw
+
+ io (removeFile path)
return $ do
- sf <- maybeRead reads =<< raw
+ sf <- join sf'
let winset = W.ensureTags layout (workspaces xmc) $ W.mapLayout (fromMaybe layout . maybeRead lreads) (sfWins sf)
extState = M.fromList . map (second Left) $ sfExt sf
@@ -491,6 +498,9 @@ readStateFile xmc = do
[(x, "")] -> Just x
_ -> Nothing
+ readStrict :: Handle -> IO String
+ readStrict h = hGetContents h >>= \s -> length s `seq` return s
+
-- | Migrate state from a previously running xmonad instance that used
-- the older @--resume@ technique.
{-# DEPRECATED migrateState "will be removed some point in the future." #-}