Skip to content

Commit f072e31

Browse files
committed
Fix race condition in IORef backend
1 parent 82ce487 commit f072e31

1 file changed

Lines changed: 12 additions & 10 deletions

File tree

src/Data/Vault/ST/backends/IORef.hs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@ type Map = Map.Map
77
{-----------------------------------------------------------------------------
88
Locker
99
------------------------------------------------------------------------------}
10-
data Key s a = Key !Unique (IORef (Maybe a))
10+
data Key s a = Key !Unique (IORef (Maybe a)) (MVar ())
1111
data Locker s = Locker !Unique (IO ())
1212

1313
#if IsStrict
14-
lock (Key u ref) x = x `seq` (Locker u $ writeIORef ref $ Just x)
14+
lock (Key u ref _) x = x `seq` (Locker u $ writeIORef ref $ Just x)
1515
#else
16-
lock (Key u ref) x = Locker u $ writeIORef ref $ Just x
16+
lock (Key u ref _) x = Locker u $ writeIORef ref $ Just x
1717
#endif
1818

19-
unlock (Key k ref) (Locker k' m)
19+
unlock (Key k ref lock) (Locker k' m)
2020
| k == k' = unsafePerformIO $ do
21+
takeMVar lock
2122
m
22-
readIORef ref -- FIXME: race condition!
23+
readIORef ref
24+
putMVar lock ()
2325
| otherwise = Nothing
2426

2527
{-----------------------------------------------------------------------------
@@ -28,13 +30,13 @@ unlock (Key k ref) (Locker k' m)
2830
-- implemented as a collection of lockers
2931
newtype Vault s = Vault (Map Unique (Locker s))
3032

31-
newKey = unsafeIOToST $ Key <$> newUnique <*> newIORef Nothing
33+
newKey = unsafeIOToST $ Key <$> newUnique <*> newIORef Nothing <*> newMVar ()
3234

33-
lookup key@(Key k _) (Vault m) = unlock key =<< Map.lookup k m
35+
lookup key@(Key k _ _) (Vault m) = unlock key =<< Map.lookup k m
3436

35-
insert key@(Key k _) x (Vault m) = Vault $ Map.insert k (lock key x) m
37+
insert key@(Key k _ _) x (Vault m) = Vault $ Map.insert k (lock key x) m
3638

37-
adjust f key@(Key k _) (Vault m) = Vault $ Map.update f' k m
39+
adjust f key@(Key k _ _) (Vault m) = Vault $ Map.update f' k m
3840
where f' = fmap (lock key . f) . unlock key
3941

40-
delete (Key k _) (Vault m) = Vault $ Map.delete k m
42+
delete (Key k _ _) (Vault m) = Vault $ Map.delete k m

0 commit comments

Comments
 (0)