func Read(b []byte) (n int, err error) {
return io.ReadFull(Reader, b)
}
+
+func warnBlocked() {
+ println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
+}
"os"
"runtime"
"sync"
+ "sync/atomic"
"time"
)
name string
f io.Reader
mu sync.Mutex
+ used int32 // atomic; whether this devReader has been used
}
// altGetRandom if non-nil specifies an OS-specific function to get
var altGetRandom func([]byte) (ok bool)
func (r *devReader) Read(b []byte) (n int, err error) {
+ if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
+ // First use of randomness. Start timer to warn about
+ // being blocked on entropy not being available.
+ t := time.AfterFunc(60*time.Second, warnBlocked)
+ defer t.Stop()
+ }
if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
return len(b), nil
}
import (
"os"
"sync"
+ "sync/atomic"
"syscall"
+ "time"
)
// Implemented by using Windows CryptoAPI 2.0.
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
type rngReader struct {
+ used int32 // atomic; whether this rngReader has been used
prov syscall.Handle
mu sync.Mutex
}
func (r *rngReader) Read(b []byte) (n int, err error) {
+ if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
+ // First use of randomness. Start timer to warn about
+ // being blocked on entropy not being available.
+ t := time.AfterFunc(60*time.Second, warnBlocked)
+ defer t.Stop()
+ }
r.mu.Lock()
if r.prov == 0 {
const provType = syscall.PROV_RSA_FULL