Correctly detect EPERM on crypto/rand.Random.Read failure
Signed-off-by: Stephen J Day <stephen.day@docker.com>master
							parent
							
								
									020bd0b45f
								
							
						
					
					
						commit
						7e35d16cb6
					
				
							
								
								
									
										25
									
								
								uuid/uuid.go
								
								
								
								
							
							
						
						
									
										25
									
								
								uuid/uuid.go
								
								
								
								
							| 
						 | 
					@ -9,6 +9,7 @@ import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -61,19 +62,15 @@ func Generate() (u UUID) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err := io.ReadFull(rand.Reader, u[:])
 | 
							_, err := io.ReadFull(rand.Reader, u[:])
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			if err == syscall.EPERM {
 | 
								if retryOnError(err) && retries < maxretries {
 | 
				
			||||||
				// EPERM represents an entropy pool exhaustion, a condition under
 | 
					 | 
				
			||||||
				// which we backoff and retry.
 | 
					 | 
				
			||||||
				if retries < maxretries {
 | 
					 | 
				
			||||||
				retries++
 | 
									retries++
 | 
				
			||||||
				Loggerf("error generating version 4 uuid, retrying: %v", err)
 | 
									Loggerf("error generating version 4 uuid, retrying: %v", err)
 | 
				
			||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Any other errors represent a system problem. What did someone
 | 
								// Any other errors represent a system problem. What did someone
 | 
				
			||||||
			// do to /dev/urandom?
 | 
								// 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
 | 
							break
 | 
				
			||||||
| 
						 | 
					@ -110,3 +107,19 @@ func Parse(s string) (u UUID, err error) {
 | 
				
			||||||
func (u UUID) String() string {
 | 
					func (u UUID) String() string {
 | 
				
			||||||
	return fmt.Sprintf(format, u[:4], u[4:6], u[6:8], u[8:10], u[10:])
 | 
						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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue