@@ -28,16 +28,20 @@ thread_local!(
2828 static RNG_SOURCE : RefCell <Option <RngSource >> = RefCell :: new( None ) ;
2929) ;
3030
31- fn syscall_getrandom ( dest : & mut [ u8 ] , block : bool ) -> Result < ( ) , io:: Error > {
31+ fn syscall_getrandom ( dest : & mut [ u8 ] , block : bool ) -> Result < usize , io:: Error > {
3232 let flags = if block { 0 } else { libc:: GRND_NONBLOCK } ;
3333 let ret = unsafe {
3434 libc:: syscall ( libc:: SYS_getrandom , dest. as_mut_ptr ( ) , dest. len ( ) , flags)
3535 } ;
36- if ret < 0 || ( ret as usize ) != dest. len ( ) {
36+ if ret < 0 {
37+ let err = io:: Error :: last_os_error ( ) ;
38+ if err. raw_os_error ( ) == Some ( libc:: EINTR ) {
39+ return Ok ( 0 ) ; // Call was interrupted, try again
40+ }
3741 error ! ( "Linux getrandom syscall failed with return value {}" , ret) ;
38- return Err ( io :: Error :: last_os_error ( ) ) ;
42+ return Err ( err ) ;
3943 }
40- Ok ( ( ) )
44+ Ok ( ret as usize )
4145}
4246
4347pub fn getrandom_inner ( dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
@@ -58,9 +62,15 @@ pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
5862 Ok ( s)
5963 } , |f| {
6064 match f {
61- RngSource :: GetRandom => syscall_getrandom ( dest, true ) ,
62- RngSource :: Device ( f) => f. read_exact ( dest) ,
63- } . map_err ( From :: from)
65+ RngSource :: GetRandom => {
66+ let mut start = 0 ;
67+ while start < dest. len ( ) {
68+ start += syscall_getrandom ( & mut dest[ start..] , true ) ?;
69+ }
70+ Ok ( ( ) )
71+ }
72+ RngSource :: Device ( f) => f. read_exact ( dest) . map_err ( From :: from) ,
73+ }
6474 } )
6575 } )
6676}
@@ -74,7 +84,7 @@ fn is_getrandom_available() -> bool {
7484 CHECKER . call_once ( || {
7585 let mut buf: [ u8 ; 0 ] = [ ] ;
7686 let available = match syscall_getrandom ( & mut buf, false ) {
77- Ok ( ( ) ) => true ,
87+ Ok ( _ ) => true ,
7888 Err ( err) => err. raw_os_error ( ) != Some ( libc:: ENOSYS ) ,
7989 } ;
8090 AVAILABLE . store ( available, Ordering :: Relaxed ) ;
0 commit comments