Skip to content

Commit 1d9e66c

Browse files
committed
auto merge of #11304 : alexcrichton/rust/eintr, r=brson
Closes #11214
2 parents 8fc148f + 674d24e commit 1d9e66c

File tree

4 files changed

+108
-70
lines changed

4 files changed

+108
-70
lines changed

src/libnative/io/file.rs

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::rt::rtio;
2020
use std::unstable::intrinsics;
2121
use std::vec;
2222

23-
use super::IoResult;
23+
use io::{IoResult, retry};
2424

2525
#[cfg(windows)] use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
2626
#[cfg(windows)] use std::ptr;
@@ -143,8 +143,8 @@ impl rtio::RtioFileStream for FileDesc {
143143
overlap.OffsetHigh = (offset >> 32) as libc::DWORD;
144144

145145
match libc::ReadFile(handle, buf as libc::LPVOID,
146-
amt as libc::DWORD,
147-
&mut bytes_read, &mut overlap) {
146+
amt as libc::DWORD,
147+
&mut bytes_read, &mut overlap) {
148148
0 => Err(super::last_error()),
149149
_ => Ok(bytes_read as int)
150150
}
@@ -153,10 +153,10 @@ impl rtio::RtioFileStream for FileDesc {
153153

154154
#[cfg(unix)]
155155
fn os_pread(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<int> {
156-
match unsafe {
156+
match retry(|| unsafe {
157157
libc::pread(fd, buf as *libc::c_void, amt as libc::size_t,
158-
offset as libc::off_t)
159-
} {
158+
offset as libc::off_t) as libc::c_int
159+
}) {
160160
-1 => Err(super::last_error()),
161161
n => Ok(n as int)
162162
}
@@ -184,10 +184,10 @@ impl rtio::RtioFileStream for FileDesc {
184184

185185
#[cfg(unix)]
186186
fn os_pwrite(fd: c_int, buf: *u8, amt: uint, offset: u64) -> IoResult<()> {
187-
super::mkerr_libc(unsafe {
187+
super::mkerr_libc(retry(|| unsafe {
188188
libc::pwrite(fd, buf as *libc::c_void, amt as libc::size_t,
189189
offset as libc::off_t)
190-
} as c_int)
190+
} as c_int))
191191
}
192192
}
193193
#[cfg(windows)]
@@ -240,7 +240,7 @@ impl rtio::RtioFileStream for FileDesc {
240240
}
241241
#[cfg(unix)]
242242
fn os_fsync(fd: c_int) -> IoResult<()> {
243-
super::mkerr_libc(unsafe { libc::fsync(fd) })
243+
super::mkerr_libc(retry(|| unsafe { libc::fsync(fd) }))
244244
}
245245
}
246246
#[cfg(windows)]
@@ -255,9 +255,13 @@ impl rtio::RtioFileStream for FileDesc {
255255
unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) }
256256
}
257257
#[cfg(target_os = "linux")]
258-
fn os_datasync(fd: c_int) -> c_int { unsafe { libc::fdatasync(fd) } }
258+
fn os_datasync(fd: c_int) -> c_int {
259+
retry(|| unsafe { libc::fdatasync(fd) })
260+
}
259261
#[cfg(not(target_os = "macos"), not(target_os = "linux"))]
260-
fn os_datasync(fd: c_int) -> c_int { unsafe { libc::fsync(fd) } }
262+
fn os_datasync(fd: c_int) -> c_int {
263+
retry(|| unsafe { libc::fsync(fd) })
264+
}
261265
}
262266

263267
#[cfg(windows)]
@@ -278,9 +282,9 @@ impl rtio::RtioFileStream for FileDesc {
278282
}
279283
#[cfg(unix)]
280284
fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
281-
super::mkerr_libc(unsafe {
285+
super::mkerr_libc(retry(|| unsafe {
282286
libc::ftruncate(self.fd, offset as libc::off_t)
283-
})
287+
}))
284288
}
285289
}
286290

@@ -311,9 +315,17 @@ impl rtio::RtioTTY for FileDesc {
311315

312316
impl Drop for FileDesc {
313317
fn drop(&mut self) {
314-
// closing stdio file handles makes no sense, so never do it
318+
// closing stdio file handles makes no sense, so never do it. Also, note
319+
// that errors are ignored when closing a file descriptor. The reason
320+
// for this is that if an error occurs we don't actually know if the
321+
// file descriptor was closed or not, and if we retried (for something
322+
// like EINTR), we might close another valid file descriptor (opened
323+
// after we closed ours.
315324
if self.close_on_drop && self.fd > libc::STDERR_FILENO {
316-
unsafe { libc::close(self.fd); }
325+
let n = unsafe { libc::close(self.fd) };
326+
if n != 0 {
327+
warn!("error {} when closing file descriptor {}", n, self.fd);
328+
}
317329
}
318330
}
319331
}
@@ -336,7 +348,7 @@ impl CFile {
336348
}
337349

338350
pub fn flush(&mut self) -> Result<(), IoError> {
339-
super::mkerr_libc(unsafe { libc::fflush(self.file) })
351+
super::mkerr_libc(retry(|| unsafe { libc::fflush(self.file) }))
340352
}
341353
}
342354

@@ -444,13 +456,13 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
444456
#[cfg(windows)]
445457
fn os_open(path: &CString, flags: c_int, mode: c_int) -> c_int {
446458
as_utf16_p(path.as_str().unwrap(), |path| {
447-
unsafe { libc::wopen(path, flags, mode) }
459+
retry(|| unsafe { libc::wopen(path, flags, mode) })
448460
})
449461
}
450462

451463
#[cfg(unix)]
452464
fn os_open(path: &CString, flags: c_int, mode: c_int) -> c_int {
453-
unsafe { libc::open(path.with_ref(|p| p), flags, mode) }
465+
retry(|| unsafe { libc::open(path.with_ref(|p| p), flags, mode) })
454466
}
455467
}
456468

@@ -469,9 +481,9 @@ pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
469481

470482
#[cfg(unix)]
471483
fn os_mkdir(p: &CString, mode: c_int) -> IoResult<()> {
472-
super::mkerr_libc(unsafe {
484+
super::mkerr_libc(retry(|| unsafe {
473485
libc::mkdir(p.with_ref(|p| p), mode as libc::mode_t)
474-
})
486+
}))
475487
}
476488
}
477489

@@ -582,7 +594,7 @@ pub fn unlink(p: &CString) -> IoResult<()> {
582594

583595
#[cfg(unix)]
584596
fn os_unlink(p: &CString) -> IoResult<()> {
585-
super::mkerr_libc(unsafe { libc::unlink(p.with_ref(|p| p)) })
597+
super::mkerr_libc(retry(|| unsafe { libc::unlink(p.with_ref(|p| p)) }))
586598
}
587599
}
588600

@@ -602,9 +614,9 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
602614

603615
#[cfg(unix)]
604616
fn os_rename(old: &CString, new: &CString) -> IoResult<()> {
605-
super::mkerr_libc(unsafe {
617+
super::mkerr_libc(retry(|| unsafe {
606618
libc::rename(old.with_ref(|p| p), new.with_ref(|p| p))
607-
})
619+
}))
608620
}
609621
}
610622

@@ -614,13 +626,15 @@ pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
614626
#[cfg(windows)]
615627
fn os_chmod(p: &CString, mode: c_int) -> c_int {
616628
unsafe {
617-
as_utf16_p(p.as_str().unwrap(), |p| libc::wchmod(p, mode))
629+
as_utf16_p(p.as_str().unwrap(), |p| retry(|| {
630+
libc::wchmod(p, mode)
631+
}))
618632
}
619633
}
620634

621635
#[cfg(unix)]
622636
fn os_chmod(p: &CString, mode: c_int) -> c_int {
623-
unsafe { libc::chmod(p.with_ref(|p| p), mode as libc::mode_t) }
637+
retry(||unsafe { libc::chmod(p.with_ref(|p| p), mode as libc::mode_t) })
624638
}
625639
}
626640

@@ -630,13 +644,15 @@ pub fn rmdir(p: &CString) -> IoResult<()> {
630644
#[cfg(windows)]
631645
fn os_rmdir(p: &CString) -> c_int {
632646
unsafe {
633-
as_utf16_p(p.as_str().unwrap(), |p| libc::wrmdir(p))
647+
as_utf16_p(p.as_str().unwrap(), |p| retry(|| {
648+
libc::wrmdir(p)
649+
}))
634650
}
635651
}
636652

637653
#[cfg(unix)]
638654
fn os_rmdir(p: &CString) -> c_int {
639-
unsafe { libc::rmdir(p.with_ref(|p| p)) }
655+
retry(|| unsafe { libc::rmdir(p.with_ref(|p| p)) })
640656
}
641657
}
642658

@@ -649,10 +665,10 @@ pub fn chown(p: &CString, uid: int, gid: int) -> IoResult<()> {
649665

650666
#[cfg(unix)]
651667
fn os_chown(p: &CString, uid: int, gid: int) -> c_int {
652-
unsafe {
668+
retry(|| unsafe {
653669
libc::chown(p.with_ref(|p| p), uid as libc::uid_t,
654670
gid as libc::gid_t)
655-
}
671+
})
656672
}
657673
}
658674

@@ -697,10 +713,10 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
697713
len = 1024; // XXX: read PATH_MAX from C ffi?
698714
}
699715
let mut buf = vec::with_capacity::<u8>(len as uint);
700-
match unsafe {
716+
match retry(|| unsafe {
701717
libc::readlink(p, buf.as_ptr() as *mut libc::c_char,
702-
len as libc::size_t)
703-
} {
718+
len as libc::size_t) as libc::c_int
719+
}) {
704720
-1 => Err(super::last_error()),
705721
n => {
706722
assert!(n > 0);
@@ -725,9 +741,9 @@ pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
725741

726742
#[cfg(unix)]
727743
fn os_symlink(src: &CString, dst: &CString) -> IoResult<()> {
728-
super::mkerr_libc(unsafe {
744+
super::mkerr_libc(retry(|| unsafe {
729745
libc::symlink(src.with_ref(|p| p), dst.with_ref(|p| p))
730-
})
746+
}))
731747
}
732748
}
733749

@@ -745,9 +761,9 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
745761

746762
#[cfg(unix)]
747763
fn os_link(src: &CString, dst: &CString) -> IoResult<()> {
748-
super::mkerr_libc(unsafe {
764+
super::mkerr_libc(retry(|| unsafe {
749765
libc::link(src.with_ref(|p| p), dst.with_ref(|p| p))
750-
})
766+
}))
751767
}
752768
}
753769

@@ -842,7 +858,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
842858
fn os_stat(p: &CString) -> IoResult<io::FileStat> {
843859
let mut stat: libc::stat = unsafe { intrinsics::uninit() };
844860
as_utf16_p(p.as_str().unwrap(), |up| {
845-
match unsafe { libc::wstat(up, &mut stat) } {
861+
match retry(|| unsafe { libc::wstat(up, &mut stat) }) {
846862
0 => Ok(mkstat(&stat, p)),
847863
_ => Err(super::last_error()),
848864
}
@@ -852,7 +868,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
852868
#[cfg(unix)]
853869
fn os_stat(p: &CString) -> IoResult<io::FileStat> {
854870
let mut stat: libc::stat = unsafe { intrinsics::uninit() };
855-
match unsafe { libc::stat(p.with_ref(|p| p), &mut stat) } {
871+
match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) {
856872
0 => Ok(mkstat(&stat, p)),
857873
_ => Err(super::last_error()),
858874
}
@@ -871,7 +887,7 @@ pub fn lstat(p: &CString) -> IoResult<io::FileStat> {
871887
#[cfg(unix)]
872888
fn os_lstat(p: &CString) -> IoResult<io::FileStat> {
873889
let mut stat: libc::stat = unsafe { intrinsics::uninit() };
874-
match unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) } {
890+
match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) {
875891
0 => Ok(mkstat(&stat, p)),
876892
_ => Err(super::last_error()),
877893
}
@@ -888,7 +904,9 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
888904
modtime: (mtime / 1000) as libc::time64_t,
889905
};
890906
unsafe {
891-
as_utf16_p(p.as_str().unwrap(), |p| libc::wutime(p, &buf))
907+
as_utf16_p(p.as_str().unwrap(), |p| retry(|| {
908+
libc::wutime(p, &buf)
909+
}))
892910
}
893911
}
894912

@@ -898,7 +916,7 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
898916
actime: (atime / 1000) as libc::time_t,
899917
modtime: (mtime / 1000) as libc::time_t,
900918
};
901-
unsafe { libc::utime(p.with_ref(|p| p), &buf) }
919+
retry(|| unsafe { libc::utime(p.with_ref(|p| p), &buf) })
902920
}
903921
}
904922

src/libnative/io/mod.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,24 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
134134
}
135135
}
136136

137+
#[cfg(windows)]
138+
#[inline]
139+
fn retry(f: || -> libc::c_int) -> libc::c_int {
140+
loop {
141+
match f() {
142+
-1 if os::errno() as int == libc::WSAEINTR as int => {}
143+
n => return n,
144+
}
145+
}
146+
}
147+
137148
#[cfg(unix)]
138-
fn retry(f: || -> libc::c_int) -> IoResult<libc::c_int> {
149+
#[inline]
150+
fn retry(f: || -> libc::c_int) -> libc::c_int {
139151
loop {
140152
match f() {
141153
-1 if os::errno() as int == libc::EINTR as int => {}
142-
-1 => return Err(last_error()),
143-
n => return Ok(n),
154+
n => return n,
144155
}
145156
}
146157
}

0 commit comments

Comments
 (0)