Ticket #1283 (closed bug: fixed)

Opened 6 years ago

Last modified 4 years ago

thread-safe getStdRandom and newStdGen

Reported by: haskell@… Owned by: simonmar
Priority: normal Milestone: 6.8.1
Component: libraries/base Version: 6.6
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Difficulty: Easy (less than 1 hour)
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Implementations of getStdRandom and newStdGen use unsynchronised calls to getStdGen and setStdGen, allowing a race condition in which duplicate random numbers can be returned in multiple threads.

Patch attached. Tested against GHC 6.6, on Linux amd64.

The following code used with +RTS -N2 demonstrates the race condition.

import Control.Concurrent
import Control.Monad
import Data.Sequence hiding (take)
import System.Random

threads = 4
samples = 5000

main = loopTest threads samples

loopTest t s = do
  isClean <- testRace t s
  putStrLn $ if isClean
    then "no race condition found"
    else "race condition found"
  loopTest t s

testRace t s = do
  ref <- liftM (take (t*s) . randoms) getStdGen
  iss <- threadRandoms t s
  return (isInterleavingOf (ref::[Int]) iss)

threadRandoms t s = do
  vs <- sequence $ replicate t $ do
    v <- newEmptyMVar
    forkIO (sequence (replicate s randomIO) >>= putMVar v)
    return v
  mapM takeMVar vs

isInterleavingOf xs yss = iio xs (viewl $ fromList yss) EmptyL where
  iio (x:xs) ((y:ys) :< yss) zss
    | x /= y = iio (x:xs) (viewl yss) (viewl (fromViewL zss |> (y:ys)))
    | x == y = iio xs (viewl ((ys <| yss) >< fromViewL zss)) EmptyL
  iio xs ([] :< yss) zss = iio xs (viewl yss) zss
  iio [] EmptyL EmptyL = True
  iio _ _ _ = False

fromViewL (EmptyL) = empty
fromViewL (x :< xs) = x <| xs

Attachments

patch Download (52.5 KB) - added by haskell@… 6 years ago.
Patch

Change History

Changed 6 years ago by haskell@…

Patch

Changed 6 years ago by simonmar

  • owner set to simonmar

I'm testing this one

Changed 6 years ago by simonmar

  • status changed from new to closed
  • resolution set to fixed

patch pushed and test added, thanks!

Changed 6 years ago by simonmar

  • milestone changed from 6.6.2 to 6.8.1

Changed 5 years ago by simonmar

  • architecture changed from Multiple to Unknown/Multiple

Changed 5 years ago by simonmar

  • os changed from Multiple to Unknown/Multiple

Changed 4 years ago by simonmar

  • difficulty changed from Easy (1 hr) to Easy (less than 1 hour)
Note: See TracTickets for help on using tickets.