-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix leak in H2 manager #155
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ import Control.Concurrent.STM | |
import Control.Exception | ||
import qualified Control.Exception as E | ||
import Data.Foldable | ||
import Data.Map (Map) | ||
import Data.Map.Strict (Map) | ||
import qualified Data.Map.Strict as Map | ||
import qualified System.TimeManager as T | ||
|
||
|
@@ -28,9 +28,14 @@ import Imports | |
---------------------------------------------------------------- | ||
|
||
-- | Manager to manage the thread and the timer. | ||
data Manager = Manager T.Manager (TVar ManagedThreads) | ||
data Manager = Manager T.Manager ManagedThreads | ||
|
||
type ManagedThreads = Map ThreadId TimeoutHandle | ||
-- | The set of managed threads | ||
-- | ||
-- This is a newtype to ensure that this is always updated strictly. | ||
newtype ManagedThreads = WrapManagedThreads | ||
{ unwrapManagedThreads :: TVar (Map ThreadId TimeoutHandle) | ||
} | ||
|
||
---------------------------------------------------------------- | ||
|
||
|
@@ -49,7 +54,7 @@ cancelTimeout ThreadWithoutTimeout = return () | |
-- by 'setAction'. This allows that the action can include | ||
-- the manager itself. | ||
start :: T.Manager -> IO Manager | ||
start timmgr = Manager timmgr <$> newTVarIO Map.empty | ||
start timmgr = Manager timmgr <$> newManagedThreads | ||
|
||
---------------------------------------------------------------- | ||
|
||
|
@@ -70,10 +75,7 @@ stopAfter :: Manager -> IO a -> (Maybe SomeException -> IO ()) -> IO a | |
stopAfter (Manager _timmgr var) action cleanup = do | ||
mask $ \unmask -> do | ||
ma <- try $ unmask action | ||
m <- atomically $ do | ||
m0 <- readTVar var | ||
writeTVar var Map.empty | ||
return m0 | ||
m <- atomically $ modifyManagedThreads var (\ts -> (Map.empty, ts)) | ||
forM_ (Map.elems m) cancelTimeout | ||
let er = either Just (const Nothing) ma | ||
forM_ (Map.keys m) $ \tid -> | ||
|
@@ -102,17 +104,17 @@ forkManagedUnmask (Manager _timmgr var) label io = | |
void $ mask_ $ forkIOWithUnmask $ \unmask -> E.handle ignore $ do | ||
labelMe label | ||
tid <- myThreadId | ||
atomically $ modifyTVar var $ Map.insert tid ThreadWithoutTimeout | ||
atomically $ modifyManagedThreads_ var $ Map.insert tid ThreadWithoutTimeout | ||
-- We catch the exception and do not rethrow it: we don't want the | ||
-- exception printed to stderr. | ||
io unmask `catch` ignore | ||
atomically $ modifyTVar var $ Map.delete tid | ||
atomically $ modifyManagedThreads_ var $ Map.delete tid | ||
where | ||
ignore (E.SomeException _) = return () | ||
|
||
waitCounter0 :: Manager -> IO () | ||
waitCounter0 (Manager _timmgr var) = atomically $ do | ||
m <- readTVar var | ||
m <- getManagedThreads var | ||
check (Map.size m == 0) | ||
|
||
---------------------------------------------------------------- | ||
|
@@ -122,5 +124,29 @@ withTimeout (Manager timmgr var) action = | |
T.withHandleKillThread timmgr (return ()) $ \th -> do | ||
tid <- myThreadId | ||
-- overriding ThreadWithoutTimeout | ||
atomically $ modifyTVar var $ Map.insert tid $ ThreadWithTimeout th | ||
atomically $ modifyManagedThreads_ var $ Map.insert tid $ ThreadWithTimeout th | ||
action th | ||
|
||
---------------------------------------------------------------- | ||
|
||
newManagedThreads :: IO ManagedThreads | ||
newManagedThreads = WrapManagedThreads <$> newTVarIO Map.empty | ||
|
||
getManagedThreads :: ManagedThreads -> STM (Map ThreadId TimeoutHandle) | ||
getManagedThreads = readTVar . unwrapManagedThreads | ||
|
||
modifyManagedThreads | ||
:: ManagedThreads | ||
-> (Map ThreadId TimeoutHandle -> (Map ThreadId TimeoutHandle, a)) | ||
-> STM a | ||
modifyManagedThreads (WrapManagedThreads var) f = do | ||
threads <- readTVar var | ||
let (threads', result) = f threads | ||
writeTVar var $! threads' -- strict update | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the critical line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that is not correct. Without the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, that is not the reason. module A where
ignore :: a -> String
ignore _ = "Hi" then in {-# LANGUAGE Strict, StrictData #-}
module B where
import A
ex1, ex2, ex3 :: IO ()
ex1 = putStrLn (ignore undefined)
ex2 = putStrLn (ignore $! undefined)
ex3 = let x = undefined in putStrLn (ignore x)
|
||
return result | ||
|
||
modifyManagedThreads_ | ||
:: ManagedThreads | ||
-> (Map ThreadId TimeoutHandle -> Map ThreadId TimeoutHandle) | ||
-> STM () | ||
modifyManagedThreads_ var f = modifyManagedThreads var (\ts -> (f ts, ())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this change doesn't do anything, it's just for clarity.