From 7e35d16cb649c25908e7752b81222245de48c824 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Tue, 16 Jun 2015 13:06:58 -0700 Subject: [PATCH] Correctly detect EPERM on crypto/rand.Random.Read failure Signed-off-by: Stephen J Day --- uuid/uuid.go | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/uuid/uuid.go b/uuid/uuid.go index af1913cd..4bdd9700 100644 --- a/uuid/uuid.go +++ b/uuid/uuid.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "log" + "os" "syscall" "time" ) @@ -61,19 +62,15 @@ func Generate() (u UUID) { _, err := io.ReadFull(rand.Reader, u[:]) if err != nil { - if err == syscall.EPERM { - // EPERM represents an entropy pool exhaustion, a condition under - // which we backoff and retry. - if retries < maxretries { - retries++ - Loggerf("error generating version 4 uuid, retrying: %v", err) - continue - } + if retryOnError(err) && retries < maxretries { + retries++ + Loggerf("error generating version 4 uuid, retrying: %v", err) + continue } // Any other errors represent a system problem. What did someone // do to /dev/urandom? - panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff, err)) + panic(fmt.Errorf("error reading random number generator, retried for %v: %v", totalBackoff.String(), err)) } break @@ -110,3 +107,19 @@ func Parse(s string) (u UUID, err error) { func (u UUID) String() string { return fmt.Sprintf(format, u[:4], u[4:6], u[6:8], u[8:10], u[10:]) } + +// retryOnError tries to detect whether or not retrying would be fruitful. +func retryOnError(err error) bool { + switch err := err.(type) { + case *os.PathError: + return retryOnError(err.Err) // unpack the target error + case syscall.Errno: + if err == syscall.EPERM { + // EPERM represents an entropy pool exhaustion, a condition under + // which we backoff and retry. + return true + } + } + + return false +}