diff options
author | Patrick Palka <patrick@parcs.ath.cx> | 2013-04-26 11:20:02 -0400 |
---|---|---|
committer | Patrick Palka <patrick@parcs.ath.cx> | 2013-08-26 22:21:16 -0400 |
commit | 25f8cc8375068f8277eeaacc530248a7b33edaa1 (patch) | |
tree | 234299892ad6cd9106ebc27c535d4a0bb7cffabf /compiler/utils | |
parent | 27d189a7fa833cb6bb33ff001d5472fbf1f589f1 (diff) | |
download | haskell-25f8cc8375068f8277eeaacc530248a7b33edaa1.tar.gz |
Binary: Make lazyGet more thread-safe
All values read lazily from the same BinHandle share the same mutable
offset variable (_off_r). If two such lazy values are simultaneously
evaluated, the two threads will step over each other when writing to
_off_r.
Fortunately, for BinMem handles, making lazyGet thread-safe is simple:
just use a fresh off_r variable when deferring the call to getAt.
For BinIO handles, a race condition still exists because IO handles
contain their own mutable file pointer variable that gets clobbered in a
similar way that _off_r would. But GHC doesn't use BinIO handles anywhere
so this particular issue could be ignored for now.
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/Binary.hs | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/compiler/utils/Binary.hs b/compiler/utils/Binary.hs index d14c326d34..1997d436f8 100644 --- a/compiler/utils/Binary.hs +++ b/compiler/utils/Binary.hs @@ -635,11 +635,16 @@ lazyPut bh a = do putAt bh pre_a q -- fill in slot before a with ptr to q seekBin bh q -- finally carry on writing at q +-- XXX: This function is not thread-safe on BinIO handles. lazyGet :: Binary a => BinHandle -> IO a lazyGet bh = do p <- get bh -- a BinPtr p_a <- tellBin bh - a <- unsafeInterleaveIO (getAt bh p_a) + a <- unsafeInterleaveIO $ do + -- NB: Use a fresh off_r variable in the child thread, for thread + -- safety. + off_r <- newFastMutInt + getAt bh { _off_r = off_r } p_a seekBin bh p -- skip over the object for now return a |