Skip to content

Commit ef3caec

Browse files
committed
Fixed error handling in AioCb::fsync, AioCb::read, and AioCb::write
Previously, the `AioCb`'s `in_progress` field would erroneously be set to `true`, even if the syscall had an error Fixes #714
1 parent a9f5c0c commit ef3caec

File tree

3 files changed

+68
-6
lines changed

3 files changed

+68
-6
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
99
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
1010
- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#XXX](https://github.com/nix-rust/nix/pull/XXX))
1111

12+
### Fixed
13+
- Fixed error handling in `AioCb::fsync`, `AioCb::read`, and `AioCb::write` ([#XXX](https://github.com/nix-rust/nix/pull/XXX))
14+
1215
## [0.9.0] 2017-07-23
1316

1417
### Added

src/sys/aio.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -232,16 +232,22 @@ impl<'a> AioCb<'a> {
232232
/// An asynchronous version of `fsync`.
233233
pub fn fsync(&mut self, mode: AioFsyncMode) -> Result<()> {
234234
let p: *mut libc::aiocb = &mut self.aiocb;
235-
self.in_progress = true;
236-
Errno::result(unsafe { libc::aio_fsync(mode as libc::c_int, p) }).map(drop)
235+
Errno::result(unsafe {
236+
libc::aio_fsync(mode as libc::c_int, p)
237+
}).map(|_| {
238+
self.in_progress = true;
239+
})
237240
}
238241

239242
/// Asynchronously reads from a file descriptor into a buffer
240243
pub fn read(&mut self) -> Result<()> {
241244
assert!(self.mutable, "Can't read into an immutable buffer");
242245
let p: *mut libc::aiocb = &mut self.aiocb;
243-
self.in_progress = true;
244-
Errno::result(unsafe { libc::aio_read(p) }).map(drop)
246+
Errno::result(unsafe {
247+
libc::aio_read(p)
248+
}).map(|_| {
249+
self.in_progress = true;
250+
})
245251
}
246252

247253
/// Retrieve return status of an asynchronous operation. Should only be
@@ -257,8 +263,11 @@ impl<'a> AioCb<'a> {
257263
/// Asynchronously writes from a buffer to a file descriptor
258264
pub fn write(&mut self) -> Result<()> {
259265
let p: *mut libc::aiocb = &mut self.aiocb;
260-
self.in_progress = true;
261-
Errno::result(unsafe { libc::aio_write(p) }).map(drop)
266+
Errno::result(unsafe {
267+
libc::aio_write(p)
268+
}).map(|_| {
269+
self.in_progress = true;
270+
})
262271
}
263272

264273
}

test/sys/test_aio.rs

+50
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use nix::sys::aio::*;
55
use nix::sys::signal::*;
66
use nix::sys::time::{TimeSpec, TimeValLike};
77
use std::io::{Write, Read, Seek, SeekFrom};
8+
use std::mem;
89
use std::ops::Deref;
910
use std::os::unix::io::AsRawFd;
1011
use std::rc::Rc;
@@ -88,6 +89,22 @@ fn test_fsync() {
8889
aiocb.aio_return().unwrap();
8990
}
9091

92+
/// `AioCb::fsync` should not modify the `AioCb` object if libc::aio_fsync returns
93+
/// an error
94+
#[test]
95+
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
96+
fn test_fsync_error() {
97+
const INITIAL: &'static [u8] = b"abcdef123456";
98+
// Create an invalid AioFsyncMode
99+
let mode = unsafe { mem::transmute(666) };
100+
let mut f = tempfile().unwrap();
101+
f.write(INITIAL).unwrap();
102+
let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
103+
0, //priority
104+
SigevNotify::SigevNone);
105+
let err = aiocb.fsync(mode);
106+
assert!(err.is_err());
107+
}
91108

92109
#[test]
93110
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
@@ -156,6 +173,24 @@ fn test_read() {
156173
assert!(EXPECT == rbuf.deref().deref());
157174
}
158175

176+
/// `AioCb::read` should not modify the `AioCb` object if libc::aio_read returns
177+
/// an error
178+
#[test]
179+
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
180+
fn test_read_error() {
181+
const INITIAL: &'static [u8] = b"abcdef123456";
182+
let rbuf = Rc::new(vec![0; 4].into_boxed_slice());
183+
let mut f = tempfile().unwrap();
184+
f.write(INITIAL).unwrap();
185+
let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
186+
-1, //an invalid offset
187+
rbuf.clone(),
188+
0, //priority
189+
SigevNotify::SigevNone,
190+
LioOpcode::LIO_NOP);
191+
assert!(aiocb.read().is_err());
192+
}
193+
159194
// Tests from_mut_slice
160195
#[test]
161196
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
@@ -230,6 +265,21 @@ fn test_write() {
230265
assert!(rbuf == EXPECT);
231266
}
232267

268+
/// `AioCb::write` should not modify the `AioCb` object if libc::aio_write returns
269+
/// an error
270+
#[test]
271+
#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
272+
fn test_write_error() {
273+
let wbuf = "CDEF".to_string().into_bytes();
274+
let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor
275+
0, //offset
276+
&wbuf,
277+
0, //priority
278+
SigevNotify::SigevNone,
279+
LioOpcode::LIO_NOP);
280+
assert!(aiocb.write().is_err());
281+
}
282+
233283
lazy_static! {
234284
pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
235285
}

0 commit comments

Comments
 (0)