@@ -7,8 +7,8 @@ use std::sync::{Arc, Mutex};
77use std:: { fmt, mem, slice} ;
88
99use windows_sys:: Win32 :: Foundation :: {
10- ERROR_BROKEN_PIPE , ERROR_IO_INCOMPLETE , ERROR_IO_PENDING , ERROR_NO_DATA , ERROR_PIPE_CONNECTED ,
11- ERROR_PIPE_LISTENING , HANDLE , INVALID_HANDLE_VALUE ,
10+ ERROR_BROKEN_PIPE , ERROR_IO_INCOMPLETE , ERROR_IO_PENDING , ERROR_MORE_DATA , ERROR_NO_DATA ,
11+ ERROR_PIPE_CONNECTED , ERROR_PIPE_LISTENING , HANDLE , INVALID_HANDLE_VALUE ,
1212} ;
1313use windows_sys:: Win32 :: Storage :: FileSystem :: {
1414 ReadFile , WriteFile , FILE_FLAG_FIRST_PIPE_INSTANCE , FILE_FLAG_OVERLAPPED , PIPE_ACCESS_DUPLEX ,
@@ -705,10 +705,13 @@ impl Inner {
705705 /// Schedules a read to happen in the background, executing an overlapped
706706 /// operation.
707707 ///
708- /// This function returns `true` if a normal error happens or if the read
709- /// is scheduled in the background. If the pipe is no longer connected
710- /// (ERROR_PIPE_LISTENING) then `false` is returned and no read is
711- /// scheduled.
708+ /// This function returns `true` if either of the following conditions are met:
709+ /// * A normal error happens
710+ /// * The read is scheduled in the background
711+ /// * Data is already available to be read (ERROR_MORE_DATA)
712+ ///
713+ /// If the pipe is no longer connected (ERROR_PIPE_LISTENING) then `false` is
714+ /// returned and no read is scheduled.
712715 fn schedule_read ( me : & Arc < Inner > , io : & mut Io , events : Option < & mut Vec < Event > > ) -> bool {
713716 // Check to see if a read is already scheduled/completed
714717 match io. read {
@@ -736,6 +739,20 @@ impl Inner {
736739 // we just need to wait for a connect.
737740 Err ( ref e) if e. raw_os_error ( ) == Some ( ERROR_PIPE_LISTENING as i32 ) => false ,
738741
742+ // If ERROR_MORE_DATA is returned, it means the slice of unused capacity of the
743+ // buffer provided is less than the amount of data available to be read. So
744+ // prioritize draining the buffer before scheduling a new read.
745+ //
746+ // Return `true` to indicate that an overlapped read was scheduled "successfully",
747+ // without actually scheduling it. Instead, update `io.read` to `State::Ok(buf, 0)`
748+ // to ensure that the next `std::io::Read::read` call is presented still with the
749+ // unread data to read from.
750+ Err ( ref e) if e. raw_os_error ( ) == Some ( ERROR_MORE_DATA as i32 ) => {
751+ io. read = State :: Ok ( buf, 0 ) ;
752+ mem:: forget ( me. clone ( ) ) ;
753+ true
754+ }
755+
739756 // If some other error happened, though, we're now readable to give
740757 // out the error.
741758 Err ( e) => {
@@ -898,6 +915,13 @@ fn read_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
898915 buf. set_len ( status. bytes_transferred ( ) as usize ) ;
899916 io. read = State :: Ok ( buf, 0 ) ;
900917 }
918+ // This is non-fatal. The buffer was simply too small for the entire message.
919+ // Deliver the bytes we got, and if the caller wants to read the rest of the
920+ // message, they can initiate another read.
921+ Err ( e) if e. raw_os_error ( ) == Some ( ERROR_MORE_DATA as i32 ) => {
922+ buf. set_len ( status. bytes_transferred ( ) as usize ) ;
923+ io. read = State :: Ok ( buf, 0 ) ;
924+ }
901925 Err ( e) => {
902926 debug_assert_eq ! ( status. bytes_transferred( ) , 0 ) ;
903927 io. read = State :: Err ( e) ;
0 commit comments