1
0
mirror of https://github.com/golang/go synced 2024-09-30 12:28:35 -06:00

crypto/rand: handle EAGAIN reads from /dev/urandom

Fixes #9205

Change-Id: Iacd608ba43332008984aa8ece17dcb5757f27b3f
Reviewed-on: https://go-review.googlesource.com/1611
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Brad Fitzpatrick 2014-12-16 15:11:43 +11:00
parent 8655f04d8e
commit 5308c6d932
2 changed files with 44 additions and 1 deletions

27
src/crypto/rand/eagain.go Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rand
import (
"os"
"syscall"
)
func init() {
isEAGAIN = unixIsEAGAIN
}
// unixIsEAGAIN reports whether err is a syscall.EAGAIN wrapped in a PathError.
// See golang.org/issue/9205
func unixIsEAGAIN(err error) bool {
if pe, ok := err.(*os.PathError); ok {
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN {
return true
}
}
return false
}

View File

@ -58,12 +58,28 @@ func (r *devReader) Read(b []byte) (n int, err error) {
if runtime.GOOS == "plan9" {
r.f = f
} else {
r.f = bufio.NewReader(f)
r.f = bufio.NewReader(hideAgainReader{f})
}
}
return r.f.Read(b)
}
var isEAGAIN func(error) bool // set by eagain.go on unix systems
// hideAgainReader masks EAGAIN reads from /dev/urandom.
// See golang.org/issue/9205
type hideAgainReader struct {
r io.Reader
}
func (hr hideAgainReader) Read(p []byte) (n int, err error) {
n, err = hr.r.Read(p)
if err != nil && isEAGAIN != nil && isEAGAIN(err) {
err = nil
}
return
}
// Alternate pseudo-random implementation for use on
// systems without a reliable /dev/urandom.