@@ -29,8 +29,8 @@ pub fn hashmap_random_keys() -> (u64, u64) {
2929mod  imp { 
3030    use  fs:: File ; 
3131    use  io:: Read ; 
32+     #[ cfg( any( target_os = "linux" ,  target_os = "android" ) ) ]  
3233    use  libc; 
33-     use  sys:: os:: errno; 
3434
3535    #[ cfg( any( target_os = "linux" ,  target_os = "android" ) ) ]  
3636    fn  getrandom ( buf :  & mut  [ u8 ] )  -> libc:: c_long  { 
@@ -40,71 +40,57 @@ mod imp {
4040    } 
4141
4242    #[ cfg( not( any( target_os = "linux" ,  target_os = "android" ) ) ) ]  
43-     fn  getrandom ( _buf :  & mut  [ u8 ] )  -> libc :: c_long  {  - 1  } 
43+     fn  getrandom_fill_bytes ( _buf :  & mut  [ u8 ] )  -> bool  {  false  } 
4444
45+     #[ cfg( any( target_os = "linux" ,  target_os = "android" ) ) ]  
4546    fn  getrandom_fill_bytes ( v :  & mut  [ u8 ] )  -> bool  { 
47+         use  sync:: atomic:: { AtomicBool ,  Ordering } ; 
48+         use  sys:: os:: errno; 
49+ 
50+         static  GETRANDOM_UNAVAILABLE :  AtomicBool  = AtomicBool :: new ( false ) ; 
51+         if  GETRANDOM_UNAVAILABLE . load ( Ordering :: Relaxed )  { 
52+             return  false ; 
53+         } 
54+ 
4655        let  mut  read = 0 ; 
4756        while  read < v. len ( )  { 
4857            let  result = getrandom ( & mut  v[ read..] ) ; 
4958            if  result == -1  { 
5059                let  err = errno ( )  as  libc:: c_int ; 
5160                if  err == libc:: EINTR  { 
5261                    continue ; 
62+                 }  else  if  err == libc:: ENOSYS  { 
63+                     GETRANDOM_UNAVAILABLE . store ( true ,  Ordering :: Relaxed ) ; 
64+                     return  false ; 
5365                }  else  if  err == libc:: EAGAIN  { 
54-                     return  false 
66+                     return  false ; 
5567                }  else  { 
5668                    panic ! ( "unexpected getrandom error: {}" ,  err) ; 
5769                } 
5870            }  else  { 
5971                read += result as  usize ; 
6072            } 
6173        } 
62- 
63-         return  true 
74+         true 
6475    } 
6576
66-     #[ cfg( any( target_os = "linux" ,  target_os = "android" ) ) ]  
67-     fn  is_getrandom_available ( )  -> bool  { 
68-         use  io; 
69-         use  sync:: atomic:: { AtomicBool ,  Ordering } ; 
70-         use  sync:: Once ; 
71- 
72-         static  CHECKER :  Once  = Once :: new ( ) ; 
73-         static  AVAILABLE :  AtomicBool  = AtomicBool :: new ( false ) ; 
74- 
75-         CHECKER . call_once ( || { 
76-             let  mut  buf:  [ u8 ;  0 ]  = [ ] ; 
77-             let  result = getrandom ( & mut  buf) ; 
78-             let  available = if  result == -1  { 
79-                 let  err = io:: Error :: last_os_error ( ) . raw_os_error ( ) ; 
80-                 err != Some ( libc:: ENOSYS ) 
81-             }  else  { 
82-                 true 
83-             } ; 
84-             AVAILABLE . store ( available,  Ordering :: Relaxed ) ; 
85-         } ) ; 
86- 
87-         AVAILABLE . load ( Ordering :: Relaxed ) 
88-     } 
89- 
90-     #[ cfg( not( any( target_os = "linux" ,  target_os = "android" ) ) ) ]  
91-     fn  is_getrandom_available ( )  -> bool  {  false  } 
92- 
9377    pub  fn  fill_bytes ( v :  & mut  [ u8 ] )  { 
9478        // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN, 
9579        // meaning it would have blocked because the non-blocking pool (urandom) 
96-         // has not initialized in the kernel yet due to a lack of entropy the  
80+         // has not initialized in the kernel yet due to a lack of entropy. The  
9781        // fallback we do here is to avoid blocking applications which could 
9882        // depend on this call without ever knowing they do and don't have a 
99-         // work around.   The PRNG of /dev/urandom will still be used but not  
100-         // over a completely full  entropy pool 
101-         if  is_getrandom_available ( )  &&  getrandom_fill_bytes ( v)  { 
102-             return 
83+         // work around. The PRNG of /dev/urandom will still be used but over a  
84+         // possibly predictable  entropy pool.  
85+         if  getrandom_fill_bytes ( v)  { 
86+             return ; 
10387        } 
10488
105-         let  mut  file = File :: open ( "/dev/urandom" ) 
106-             . expect ( "failed to open /dev/urandom" ) ; 
107-         file. read_exact ( v) . expect ( "failed to read /dev/urandom" ) ; 
89+         // getrandom failed because it is permanently or temporarily (because 
90+         // of missing entropy) unavailable. Open /dev/urandom, read from it, 
91+         // and close it again. 
92+         let  mut  file = File :: open ( "/dev/urandom" ) . expect ( "failed to open /dev/urandom" ) ; 
93+         file. read_exact ( v) . expect ( "failed to read /dev/urandom" ) 
10894    } 
10995} 
11096
0 commit comments