Skip to content

Commit

Permalink
reset RandomDevice file from __init__ (JuliaLang#42537)
Browse files Browse the repository at this point in the history
This prevents us from seeing an invalid `IOStream` object from a saved
system image, and also ensures the files are opened once for all
threads.
  • Loading branch information
JeffBezanson authored Oct 27, 2021
1 parent 05ed348 commit c74814e
Showing 1 changed file with 22 additions and 8 deletions.
30 changes: 22 additions & 8 deletions stdlib/Random/src/RNGs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,26 @@ else # !windows
rand(rd::RandomDevice, sp::SamplerBoolBitInteger) = read(getfile(rd), sp[])
rand(rd::RandomDevice, ::SamplerType{Bool}) = read(getfile(rd), UInt8) % Bool

function getfile(rd::RandomDevice)
devrandom = rd.unlimited ? DEV_URANDOM : DEV_RANDOM
# TODO: there is a data-race, this can leak up to nthreads() copies of the file descriptors,
# so use a "thread-once" utility once available
isassigned(devrandom) || (devrandom[] = open(rd.unlimited ? "/dev/urandom" : "/dev/random"))
devrandom[]
mutable struct FileRef
@atomic file::Union{IOStream, Nothing}
end

const DEV_RANDOM = Ref{IOStream}()
const DEV_URANDOM = Ref{IOStream}()
const DEV_RANDOM = FileRef(nothing)
const DEV_URANDOM = FileRef(nothing)

function getfile(rd::RandomDevice)
ref = rd.unlimited ? DEV_URANDOM : DEV_RANDOM
fd = ref.file
if fd === nothing
fd = open(rd.unlimited ? "/dev/urandom" : "/dev/random")
old, ok = @atomicreplace ref.file nothing => fd
if !ok
close(fd)
fd = old::IOStream
end
end
return fd
end

end # os-test

Expand Down Expand Up @@ -411,6 +421,10 @@ for T in BitInteger_types
end

function __init__()
@static if !Sys.iswindows()
@atomic DEV_RANDOM.file = nothing
@atomic DEV_URANDOM.file = nothing
end
seed!(GLOBAL_RNG)
end

Expand Down

0 comments on commit c74814e

Please sign in to comment.