Skip to content

Commit 4443fb3

Browse files
committed
auto merge of #12855 : alexcrichton/rust/shutdown, r=brson
This is something that is plausibly useful, and is provided by libuv. This is not currently surfaced as part of the `TcpStream` type, but it may possibly appear in the future. For now only the raw functionality is provided through the Rtio objects.
2 parents 98fa0f8 + a63deeb commit 4443fb3

File tree

6 files changed

+78
-0
lines changed

6 files changed

+78
-0
lines changed

src/libnative/io/net.rs

+5
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ impl rtio::RtioTcpStream for TcpStream {
351351
fn clone(&self) -> ~rtio::RtioTcpStream {
352352
~TcpStream { inner: self.inner.clone() } as ~rtio::RtioTcpStream
353353
}
354+
fn close_write(&mut self) -> IoResult<()> {
355+
super::mkerr_libc(unsafe {
356+
libc::shutdown(self.fd(), libc::SHUT_WR)
357+
})
358+
}
354359
}
355360

356361
impl rtio::RtioSocket for TcpStream {

src/librustuv/net.rs

+32
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,38 @@ impl rtio::RtioTcpStream for TcpWatcher {
305305
read_access: self.read_access.clone(),
306306
} as ~rtio::RtioTcpStream
307307
}
308+
309+
fn close_write(&mut self) -> Result<(), IoError> {
310+
struct Ctx {
311+
slot: Option<BlockedTask>,
312+
status: c_int,
313+
}
314+
let mut req = Request::new(uvll::UV_SHUTDOWN);
315+
316+
return match unsafe {
317+
uvll::uv_shutdown(req.handle, self.handle, shutdown_cb)
318+
} {
319+
0 => {
320+
req.defuse(); // uv callback now owns this request
321+
let mut cx = Ctx { slot: None, status: 0 };
322+
323+
wait_until_woken_after(&mut cx.slot, &self.uv_loop(), || {
324+
req.set_data(&cx);
325+
});
326+
327+
status_to_io_result(cx.status)
328+
}
329+
n => Err(uv_error_to_io_error(UvError(n)))
330+
};
331+
332+
extern fn shutdown_cb(req: *uvll::uv_shutdown_t, status: libc::c_int) {
333+
let req = Request::wrap(req);
334+
assert!(status != uvll::ECANCELED);
335+
let cx: &mut Ctx = unsafe { req.get_data() };
336+
cx.status = status;
337+
wakeup(&mut cx.slot);
338+
}
339+
}
308340
}
309341

310342
impl UvHandle<uvll::uv_tcp_t> for TcpWatcher {

src/librustuv/uvll.rs

+4
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ pub type uv_process_t = c_void;
157157
pub type uv_pipe_t = c_void;
158158
pub type uv_tty_t = c_void;
159159
pub type uv_signal_t = c_void;
160+
pub type uv_shutdown_t = c_void;
160161

161162
pub struct uv_timespec_t {
162163
tv_sec: libc::c_long,
@@ -248,6 +249,7 @@ pub type uv_exit_cb = extern "C" fn(handle: *uv_process_t,
248249
pub type uv_signal_cb = extern "C" fn(handle: *uv_signal_t,
249250
signum: c_int);
250251
pub type uv_fs_cb = extern "C" fn(req: *uv_fs_t);
252+
pub type uv_shutdown_cb = extern "C" fn(req: *uv_shutdown_t, status: c_int);
251253

252254
#[cfg(unix)] pub type uv_uid_t = libc::types::os::arch::posix88::uid_t;
253255
#[cfg(unix)] pub type uv_gid_t = libc::types::os::arch::posix88::gid_t;
@@ -539,6 +541,8 @@ extern {
539541
on_alloc: uv_alloc_cb,
540542
on_read: uv_read_cb) -> c_int;
541543
pub fn uv_read_stop(stream: *uv_stream_t) -> c_int;
544+
pub fn uv_shutdown(req: *uv_shutdown_t, handle: *uv_stream_t,
545+
cb: uv_shutdown_cb) -> c_int;
542546

543547
// idle bindings
544548
pub fn uv_idle_init(l: *uv_loop_t, i: *uv_idle_t) -> c_int;

src/libstd/io/net/tcp.rs

+18
Original file line numberDiff line numberDiff line change
@@ -710,5 +710,23 @@ mod test {
710710

711711
rx.recv();
712712
})
713+
714+
iotest!(fn shutdown_smoke() {
715+
use rt::rtio::RtioTcpStream;
716+
717+
let addr = next_test_ip4();
718+
let a = TcpListener::bind(addr).unwrap().listen();
719+
spawn(proc() {
720+
let mut a = a;
721+
let mut c = a.accept().unwrap();
722+
assert_eq!(c.read_to_end(), Ok(~[]));
723+
c.write([1]).unwrap();
724+
});
725+
726+
let mut s = TcpStream::connect(addr).unwrap();
727+
assert!(s.obj.close_write().is_ok());
728+
assert!(s.write([1]).is_err());
729+
assert_eq!(s.read_to_end(), Ok(~[1]));
730+
})
713731
}
714732

src/libstd/libc.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1611,6 +1611,10 @@ pub mod consts {
16111611
pub static SO_KEEPALIVE: c_int = 8;
16121612
pub static SO_BROADCAST: c_int = 32;
16131613
pub static SO_REUSEADDR: c_int = 4;
1614+
1615+
pub static SHUT_RD: c_int = 0;
1616+
pub static SHUT_WR: c_int = 1;
1617+
pub static SHUT_RDWR: c_int = 2;
16141618
}
16151619
pub mod extra {
16161620
use libc::types::os::arch::c95::c_int;
@@ -2391,6 +2395,10 @@ pub mod consts {
23912395
pub static SO_KEEPALIVE: c_int = 9;
23922396
pub static SO_BROADCAST: c_int = 6;
23932397
pub static SO_REUSEADDR: c_int = 2;
2398+
2399+
pub static SHUT_RD: c_int = 0;
2400+
pub static SHUT_WR: c_int = 1;
2401+
pub static SHUT_RDWR: c_int = 2;
23942402
}
23952403
#[cfg(target_arch = "x86")]
23962404
#[cfg(target_arch = "x86_64")]
@@ -2842,6 +2850,10 @@ pub mod consts {
28422850
pub static SO_KEEPALIVE: c_int = 0x0008;
28432851
pub static SO_BROADCAST: c_int = 0x0020;
28442852
pub static SO_REUSEADDR: c_int = 0x0004;
2853+
2854+
pub static SHUT_RD: c_int = 0;
2855+
pub static SHUT_WR: c_int = 1;
2856+
pub static SHUT_RDWR: c_int = 2;
28452857
}
28462858
pub mod extra {
28472859
use libc::types::os::arch::c95::c_int;
@@ -3221,6 +3233,10 @@ pub mod consts {
32213233
pub static SO_KEEPALIVE: c_int = 0x0008;
32223234
pub static SO_BROADCAST: c_int = 0x0020;
32233235
pub static SO_REUSEADDR: c_int = 0x0004;
3236+
3237+
pub static SHUT_RD: c_int = 0;
3238+
pub static SHUT_WR: c_int = 1;
3239+
pub static SHUT_RDWR: c_int = 2;
32243240
}
32253241
pub mod extra {
32263242
use libc::types::os::arch::c95::c_int;
@@ -3918,6 +3934,7 @@ pub mod funcs {
39183934
pub fn sendto(socket: c_int, buf: *c_void, len: size_t,
39193935
flags: c_int, addr: *sockaddr,
39203936
addrlen: socklen_t) -> ssize_t;
3937+
pub fn shutdown(socket: c_int, how: c_int) -> c_int;
39213938
}
39223939
}
39233940

@@ -3954,6 +3971,7 @@ pub mod funcs {
39543971
pub fn sendto(socket: SOCKET, buf: *c_void, len: c_int,
39553972
flags: c_int, addr: *sockaddr,
39563973
addrlen: c_int) -> c_int;
3974+
pub fn shutdown(socket: SOCKET, how: c_int) -> c_int;
39573975
}
39583976
}
39593977

src/libstd/rt/rtio.rs

+1
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ pub trait RtioTcpStream : RtioSocket {
206206
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError>;
207207
fn letdie(&mut self) -> Result<(), IoError>;
208208
fn clone(&self) -> ~RtioTcpStream;
209+
fn close_write(&mut self) -> Result<(), IoError>;
209210
}
210211

211212
pub trait RtioSocket {

0 commit comments

Comments
 (0)