@@ -84,6 +84,7 @@ struct Inner {
8484 connect : Overlapped ,
8585 read : Overlapped ,
8686 write : Overlapped ,
87+ event : Overlapped ,
8788 // END NOTE.
8889 handle : Handle ,
8990 connecting : AtomicBool ,
@@ -110,10 +111,16 @@ impl Inner {
110111
111112 /// Same as [`ptr_from_conn_overlapped`] but for `Inner.write`.
112113 unsafe fn ptr_from_write_overlapped ( ptr : * mut OVERLAPPED ) -> * const Inner {
113- // `read ` is after `connect: Overlapped` and `read: Overlapped`.
114+ // `write ` is after `connect: Overlapped` and `read: Overlapped`.
114115 ( ptr as * mut Overlapped ) . wrapping_sub ( 2 ) as * const Inner
115116 }
116117
118+ /// Same as [`ptr_from_conn_overlapped`] but for `Inner.event`.
119+ unsafe fn ptr_from_event_overlapped ( ptr : * mut OVERLAPPED ) -> * const Inner {
120+ // `event` is after `connect: Overlapped`, `read: Overlapped`, and `write: Overlapped`.
121+ ( ptr as * mut Overlapped ) . wrapping_sub ( 3 ) as * const Inner
122+ }
123+
117124 /// Issue a connection request with the specified overlapped operation.
118125 ///
119126 /// This function will issue a request to connect a client to this server,
@@ -478,6 +485,7 @@ impl FromRawHandle for NamedPipe {
478485 connecting : AtomicBool :: new ( false ) ,
479486 read : Overlapped :: new ( read_done) ,
480487 write : Overlapped :: new ( write_done) ,
488+ event : Overlapped :: new ( event_done) ,
481489 io : Mutex :: new ( Io {
482490 cp : None ,
483491 token : None ,
@@ -724,7 +732,7 @@ impl Inner {
724732 // out the error.
725733 Err ( e) => {
726734 io. read = State :: Err ( e) ;
727- io. notify_readable ( events) ;
735+ io. notify_readable ( me , events) ;
728736 true
729737 }
730738 }
@@ -787,7 +795,7 @@ impl Inner {
787795 Ok ( None ) => ( ) ,
788796 Err ( e) => {
789797 io. write = State :: Err ( e) ;
790- io. notify_writable ( events) ;
798+ io. notify_writable ( me , events) ;
791799 }
792800 }
793801 }
@@ -797,7 +805,7 @@ impl Inner {
797805 #[ allow( clippy:: needless_option_as_deref) ]
798806 if Inner :: schedule_read ( me, & mut io, events. as_deref_mut ( ) ) {
799807 if let State :: None = io. write {
800- io. notify_writable ( events) ;
808+ io. notify_writable ( me , events) ;
801809 }
802810 }
803811 }
@@ -877,7 +885,7 @@ fn read_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
877885 }
878886
879887 // Flag our readiness that we've got data.
880- io. notify_readable ( events) ;
888+ io. notify_readable ( & me , events) ;
881889}
882890
883891fn write_done ( status : & OVERLAPPED_ENTRY , events : Option < & mut Vec < Event > > ) {
@@ -895,7 +903,7 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
895903 // `Ok` here means, that the operation was completed immediately
896904 // `bytes_transferred` is already reported to a client
897905 State :: Ok ( ..) => {
898- io. notify_writable ( events) ;
906+ io. notify_writable ( & me , events) ;
899907 return ;
900908 }
901909 State :: Pending ( buf, pos) => ( buf, pos) ,
@@ -909,20 +917,46 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
909917 let new_pos = pos + ( status. bytes_transferred ( ) as usize ) ;
910918 if new_pos == buf. len ( ) {
911919 me. put_buffer ( buf) ;
912- io. notify_writable ( events) ;
920+ io. notify_writable ( & me , events) ;
913921 } else {
914922 Inner :: schedule_write ( & me, buf, new_pos, & mut io, events) ;
915923 }
916924 }
917925 Err ( e) => {
918926 debug_assert_eq ! ( status. bytes_transferred( ) , 0 ) ;
919927 io. write = State :: Err ( e) ;
920- io. notify_writable ( events) ;
928+ io. notify_writable ( & me , events) ;
921929 }
922930 }
923931 }
924932}
925933
934+ fn event_done ( status : & OVERLAPPED_ENTRY , events : Option < & mut Vec < Event > > ) {
935+ let status = CompletionStatus :: from_entry ( status) ;
936+
937+ // Acquire the `Arc<Inner>`. Note that we should be guaranteed that
938+ // the refcount is available to us due to the `mem::forget` in
939+ // `schedule_write` above.
940+ let me = unsafe { Arc :: from_raw ( Inner :: ptr_from_event_overlapped ( status. overlapped ( ) ) ) } ;
941+
942+ let io = me. io . lock ( ) . unwrap ( ) ;
943+
944+ // Make sure the I/O handle is still registered with the selector
945+ if io. token . is_some ( ) {
946+ // This method is also called during `Selector::drop` to perform
947+ // cleanup. In this case, `events` is `None` and we don't need to track
948+ // the event.
949+ if let Some ( events) = events {
950+ let mut ev = Event :: from_completion_status ( & status) ;
951+ // Reverse the `.data` alteration done in `schedule_event`. This
952+ // alteration was done so the selector recognized the event as one from
953+ // a named pipe.
954+ ev. data >>= 1 ;
955+ events. push ( ev) ;
956+ }
957+ }
958+ }
959+
926960impl Io {
927961 fn check_association ( & self , registry : & Registry , required : bool ) -> io:: Result < ( ) > {
928962 match self . cp {
@@ -938,28 +972,53 @@ impl Io {
938972 }
939973 }
940974
941- fn notify_readable ( & self , events : Option < & mut Vec < Event > > ) {
975+ fn notify_readable ( & self , me : & Arc < Inner > , events : Option < & mut Vec < Event > > ) {
942976 if let Some ( token) = self . token {
943977 let mut ev = Event :: new ( token) ;
944978 ev. set_readable ( ) ;
945979
946980 if let Some ( events) = events {
947981 events. push ( ev) ;
948982 } else {
949- let _ = self . cp . as_ref ( ) . unwrap ( ) . post ( ev . to_completion_status ( ) ) ;
983+ self . schedule_event ( me , ev ) ;
950984 }
951985 }
952986 }
953987
954- fn notify_writable ( & self , events : Option < & mut Vec < Event > > ) {
988+ fn notify_writable ( & self , me : & Arc < Inner > , events : Option < & mut Vec < Event > > ) {
955989 if let Some ( token) = self . token {
956990 let mut ev = Event :: new ( token) ;
957991 ev. set_writable ( ) ;
958992
959993 if let Some ( events) = events {
960994 events. push ( ev) ;
961995 } else {
962- let _ = self . cp . as_ref ( ) . unwrap ( ) . post ( ev. to_completion_status ( ) ) ;
996+ self . schedule_event ( me, ev) ;
997+ }
998+ }
999+ }
1000+
1001+ fn schedule_event ( & self , me : & Arc < Inner > , mut event : Event ) {
1002+ // Alter the token so that the selector will identify the IOCP event as
1003+ // one for a named pipe. This will be reversed in `event_done`
1004+ //
1005+ // `data` for named pipes is an auto-incrementing counter. Because
1006+ // `data` is `u64` we do not risk losing the most-significant bit
1007+ // (unless a user creates 2^62 named pipes during the lifetime of the
1008+ // process).
1009+ event. data <<= 1 ;
1010+ event. data += 1 ;
1011+
1012+ let completion_status =
1013+ event. to_completion_status_with_overlapped ( me. event . as_ptr ( ) as * mut _ ) ;
1014+
1015+ match self . cp . as_ref ( ) . unwrap ( ) . post ( completion_status) {
1016+ Ok ( _) => {
1017+ // Increase the ref count of `Inner` for the completion event.
1018+ mem:: forget ( me. clone ( ) ) ;
1019+ }
1020+ Err ( _) => {
1021+ // Nothing to do here
9631022 }
9641023 }
9651024 }
0 commit comments