package rand
import (
"crypto/internal/boring"
"errors"
"io"
"os"
"sync"
"sync/atomic"
"syscall"
"time"
)
const urandomDevice = "/dev/urandom"
func init () {
if boring .Enabled {
Reader = boring .RandReader
return
}
Reader = &reader {}
}
type reader struct {
f io .Reader
mu sync .Mutex
used atomic .Uint32
}
var altGetRandom func ([]byte ) (err error )
func warnBlocked () {
println ("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel" )
}
func (r *reader ) Read (b []byte ) (n int , err error ) {
boring .Unreachable ()
if r .used .CompareAndSwap (0 , 1 ) {
t := time .AfterFunc (time .Minute , warnBlocked )
defer t .Stop ()
}
if altGetRandom != nil && altGetRandom (b ) == nil {
return len (b ), nil
}
if r .used .Load () != 2 {
r .mu .Lock ()
if r .used .Load () != 2 {
f , err := os .Open (urandomDevice )
if err != nil {
r .mu .Unlock ()
return 0 , err
}
r .f = hideAgainReader {f }
r .used .Store (2 )
}
r .mu .Unlock ()
}
return io .ReadFull (r .f , b )
}
type hideAgainReader struct {
r io .Reader
}
func (hr hideAgainReader ) Read (p []byte ) (n int , err error ) {
n , err = hr .r .Read (p )
if errors .Is (err , syscall .EAGAIN ) {
err = nil
}
return
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .