File tree Expand file tree Collapse file tree 3 files changed +38
-8
lines changed Expand file tree Collapse file tree 3 files changed +38
-8
lines changed Original file line number Diff line number Diff line change @@ -623,8 +623,8 @@ impl<T: Write> AsyncWrite for Async<T> {
623
623
poll_once ( cx, self . write_with_mut ( |io| io. flush ( ) ) )
624
624
}
625
625
626
- fn poll_close ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
627
- self . poll_flush ( cx )
626
+ fn poll_close ( self : Pin < & mut Self > , _ : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
627
+ Poll :: Ready ( self . source . shutdown_write ( ) )
628
628
}
629
629
}
630
630
@@ -652,8 +652,8 @@ where
652
652
poll_once ( cx, self . write_with ( |io| ( & * io) . flush ( ) ) )
653
653
}
654
654
655
- fn poll_close ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
656
- self . poll_flush ( cx )
655
+ fn poll_close ( self : Pin < & mut Self > , _ : & mut Context < ' _ > ) -> Poll < io:: Result < ( ) > > {
656
+ Poll :: Ready ( self . source . shutdown_write ( ) )
657
657
}
658
658
}
659
659
Original file line number Diff line number Diff line change 7
7
use std:: collections:: BTreeMap ;
8
8
use std:: fmt;
9
9
use std:: io;
10
- use std:: mem;
10
+ use std:: mem:: { self , ManuallyDrop } ;
11
+ use std:: net:: { Shutdown , TcpStream } ;
11
12
#[ cfg( unix) ]
12
- use std:: os:: unix:: io:: RawFd ;
13
+ use std:: os:: unix:: io:: { FromRawFd , RawFd } ;
13
14
#[ cfg( windows) ]
14
- use std:: os:: windows:: io:: RawSocket ;
15
+ use std:: os:: windows:: io:: { FromRawSocket , RawSocket } ;
15
16
use std:: panic;
16
17
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
17
18
use std:: sync:: { Arc , Condvar , Mutex , MutexGuard } ;
@@ -739,4 +740,21 @@ impl Source {
739
740
} )
740
741
. await
741
742
}
743
+
744
+ /// Shuts down the write side of the socket.
745
+ ///
746
+ /// If this source is not a socket, the `shutdown` syscall error is ignored.
747
+ pub ( crate ) fn shutdown_write ( & self ) -> io:: Result < ( ) > {
748
+ // This may not be a TCP stream, but that's okay - all we do is call `shutdown()` on it.
749
+ #[ cfg( unix) ]
750
+ let stream = unsafe { ManuallyDrop :: new ( TcpStream :: from_raw_fd ( self . raw ) ) } ;
751
+ #[ cfg( windows) ]
752
+ let stream = unsafe { ManuallyDrop :: new ( TcpStream :: from_raw_socket ( self . raw ) ) } ;
753
+
754
+ // The only actual error may be ENOTCONN.
755
+ match stream. shutdown ( Shutdown :: Write ) {
756
+ Err ( err) if err. kind ( ) == io:: ErrorKind :: NotConnected => Err ( err) ,
757
+ _ => Ok ( ( ) ) ,
758
+ }
759
+ }
742
760
}
Original file line number Diff line number Diff line change @@ -9,7 +9,7 @@ use std::time::Duration;
9
9
10
10
use async_io:: { Async , Timer } ;
11
11
use blocking:: block_on;
12
- use futures:: { AsyncReadExt , AsyncWriteExt , StreamExt } ;
12
+ use futures:: { future , AsyncReadExt , AsyncWriteExt , StreamExt } ;
13
13
#[ cfg( unix) ]
14
14
use tempfile:: tempdir;
15
15
@@ -337,3 +337,15 @@ fn tcp_duplex() -> io::Result<()> {
337
337
Ok ( ( ) )
338
338
} )
339
339
}
340
+
341
+ #[ test]
342
+ fn close ( ) -> io:: Result < ( ) > {
343
+ block_on ( async {
344
+ let ( mut reader, mut writer) = Async :: < UnixStream > :: pair ( ) ?;
345
+ let mut buf = Vec :: new ( ) ;
346
+
347
+ // The writer must be closed in order for `read_to_end()` to finish.
348
+ future:: try_join ( reader. read_to_end ( & mut buf) , writer. close ( ) ) . await ?;
349
+ Ok ( ( ) )
350
+ } )
351
+ }
You can’t perform that action at this time.
0 commit comments