Skip to content

Commit ae26e7c

Browse files
committed
Fix memory leak in terminal output.
1 parent 136fd37 commit ae26e7c

File tree

2 files changed

+31
-59
lines changed

2 files changed

+31
-59
lines changed

Test/QuickCheck/State.hs

+10-10
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ data State
2121
-- #tests and #discarded tests
2222

2323
-- dynamic
24-
, numSuccessTests :: Int -- ^ the current number of tests that have succeeded
25-
, numDiscardedTests :: Int -- ^ the current number of discarded tests
26-
, numRecentlyDiscardedTests :: Int -- ^ the number of discarded tests since the last successful test
27-
, labels :: Map String Int -- ^ all labels that have been defined so far
28-
, collected :: [[String]] -- ^ all labels that have been collected so far
29-
, expectedFailure :: Bool -- ^ indicates if the property is expected to fail
30-
, randomSeed :: QCGen -- ^ the current random seed
24+
, numSuccessTests :: !Int -- ^ the current number of tests that have succeeded
25+
, numDiscardedTests :: !Int -- ^ the current number of discarded tests
26+
, numRecentlyDiscardedTests :: !Int -- ^ the number of discarded tests since the last successful test
27+
, labels :: !(Map String Int) -- ^ all labels that have been defined so far
28+
, collected :: ![[String]] -- ^ all labels that have been collected so far
29+
, expectedFailure :: !Bool -- ^ indicates if the property is expected to fail
30+
, randomSeed :: !QCGen -- ^ the current random seed
3131

3232
-- shrinking
33-
, numSuccessShrinks :: Int -- ^ number of successful shrinking steps so far
34-
, numTryShrinks :: Int -- ^ number of failed shrinking steps since the last successful shrink
35-
, numTotTryShrinks :: Int -- ^ total number of failed shrinking steps
33+
, numSuccessShrinks :: !Int -- ^ number of successful shrinking steps so far
34+
, numTryShrinks :: !Int -- ^ number of failed shrinking steps since the last successful shrink
35+
, numTotTryShrinks :: !Int -- ^ total number of failed shrinking steps
3636
}
3737

3838
--------------------------------------------------------------------------

Test/QuickCheck/Text.hs

+21-49
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,13 @@ bold s = s -- for now
8585
-- putting strings
8686

8787
data Terminal
88-
= MkTerminal (IORef (IO ())) Output Output
88+
= MkTerminal (IORef String) (IORef Int) (String -> IO ()) (String -> IO ())
8989

90-
data Output
91-
= Output (String -> IO ()) (IORef String)
92-
93-
newTerminal :: Output -> Output -> IO Terminal
90+
newTerminal :: (String -> IO ()) -> (String -> IO ()) -> IO Terminal
9491
newTerminal out err =
95-
do ref <- newIORef (return ())
96-
return (MkTerminal ref out err)
92+
do res <- newIORef ""
93+
tmp <- newIORef 0
94+
return (MkTerminal res tmp out err)
9795

9896
withBuffering :: IO a -> IO a
9997
withBuffering action = do
@@ -104,65 +102,39 @@ withBuffering action = do
104102
action `finally` hSetBuffering stderr mode
105103

106104
withStdioTerminal :: (Terminal -> IO a) -> IO a
107-
withStdioTerminal action = do
108-
out <- output (handle stdout)
109-
err <- output (handle stderr)
110-
withBuffering (newTerminal out err >>= action)
105+
withStdioTerminal action =
106+
withBuffering (newTerminal (handle stdout) (handle stderr) >>= action)
111107

112108
withNullTerminal :: (Terminal -> IO a) -> IO a
113-
withNullTerminal action = do
114-
out <- output (const (return ()))
115-
err <- output (const (return ()))
116-
newTerminal out err >>= action
109+
withNullTerminal action =
110+
newTerminal (const (return ())) (const (return ())) >>= action
117111

118112
terminalOutput :: Terminal -> IO String
119-
terminalOutput (MkTerminal _ out _) = get out
113+
terminalOutput (MkTerminal res _ _ _) = readIORef res
120114

121115
handle :: Handle -> String -> IO ()
122116
handle h s = do
123117
hPutStr h s
124118
hFlush h
125119

126-
output :: (String -> IO ()) -> IO Output
127-
output f = do
128-
r <- newIORef ""
129-
return (Output f r)
130-
131-
put :: Output -> String -> IO ()
132-
put (Output f r) s = do
133-
f s
134-
modifyIORef r (++ s)
135-
136-
get :: Output -> IO String
137-
get (Output _ r) = readIORef r
138-
139120
flush :: Terminal -> IO ()
140-
flush (MkTerminal ref _ _) =
141-
do io <- readIORef ref
142-
writeIORef ref (return ())
143-
io
144-
145-
postpone :: Terminal -> IO () -> IO ()
146-
postpone (MkTerminal ref _ _) io' =
147-
do io <- readIORef ref
148-
writeIORef ref (io >> io')
121+
flush (MkTerminal _ tmp _ err) =
122+
do n <- readIORef tmp
123+
writeIORef tmp 0
124+
err (replicate n ' ' ++ replicate n '\b')
149125

150126
putPart, putTemp, putLine :: Terminal -> String -> IO ()
151-
putPart tm@(MkTerminal _ out _) s =
127+
putPart tm@(MkTerminal res _ out _) s =
152128
do flush tm
153-
put out s
129+
out s
130+
modifyIORef' res (++ s)
154131

155-
putTemp tm@(MkTerminal _ _ err) s =
156-
do flush tm
157-
put err (s ++ [ '\b' | _ <- s ])
158-
postpone tm $
159-
put err ( [ ' ' | _ <- s ]
160-
++ [ '\b' | _ <- s ]
161-
)
132+
putLine tm s = putPart tm (s ++ "\n")
162133

163-
putLine tm@(MkTerminal _ out _) s =
134+
putTemp tm@(MkTerminal _ tmp _ err) s =
164135
do flush tm
165-
put out (s ++ "\n")
136+
err (s ++ [ '\b' | _ <- s ])
137+
modifyIORef' tmp (+ length s)
166138

167139
--------------------------------------------------------------------------
168140
-- the end.

0 commit comments

Comments
 (0)