Skip to content

Commit 375082f

Browse files
committed
Add PhantomData to AioCb to track buffer's lifetime
1 parent d3f9b96 commit 375082f

File tree

2 files changed

+90
-89
lines changed

2 files changed

+90
-89
lines changed

src/sys/aio.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use {Error, Errno, Result};
22
use std::os::unix::io::RawFd;
33
use libc::{c_void, off_t, size_t};
44
use libc;
5+
use std::marker::PhantomData;
56
use std::mem;
67
use std::ptr::{null, null_mut};
78
use sys::signal::*;
@@ -59,11 +60,12 @@ pub enum AioCancelStat {
5960
/// The basic structure used by all aio functions. Each `aiocb` represents one
6061
/// I/O request.
6162
#[repr(C)]
62-
pub struct AioCb {
63-
aiocb: libc::aiocb
63+
pub struct AioCb<'a> {
64+
aiocb: libc::aiocb,
65+
phantom: PhantomData<&'a mut [u8]>
6466
}
6567

66-
impl AioCb {
68+
impl<'a> AioCb<'a> {
6769
/// Constructs a new `AioCb` with no associated buffer.
6870
///
6971
/// The resulting `AioCb` structure is suitable for use with `aio_fsync`.
@@ -73,13 +75,13 @@ impl AioCb {
7375
/// * `sigev_notify` Determines how you will be notified of event
7476
/// completion.
7577
pub fn from_fd(fd: RawFd, prio: ::c_int,
76-
sigev_notify: SigevNotify) -> AioCb {
78+
sigev_notify: SigevNotify) -> AioCb<'a> {
7779
let mut a = AioCb::common_init(fd, prio, sigev_notify);
7880
a.aio_offset = 0;
7981
a.aio_nbytes = 0;
8082
a.aio_buf = null_mut();
8183

82-
let aiocb = AioCb { aiocb: a};
84+
let aiocb = AioCb { aiocb: a, phantom: PhantomData};
8385
aiocb
8486
}
8587

@@ -94,7 +96,7 @@ impl AioCb {
9496
/// completion.
9597
/// * `opcode` This field is only used for `lio_listio`. It determines
9698
/// which operation to use for this individual aiocb
97-
pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &mut [u8],
99+
pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
98100
prio: ::c_int, sigev_notify: SigevNotify,
99101
opcode: LioOpcode) -> AioCb {
100102
let mut a = AioCb::common_init(fd, prio, sigev_notify);
@@ -103,7 +105,7 @@ impl AioCb {
103105
a.aio_buf = buf.as_ptr() as *mut c_void;
104106
a.aio_lio_opcode = opcode as ::c_int;
105107

106-
let aiocb = AioCb { aiocb: a};
108+
let aiocb = AioCb { aiocb: a, phantom: PhantomData};
107109
aiocb
108110
}
109111

@@ -121,7 +123,7 @@ impl AioCb {
121123
// lio_listio wouldn't work, because that function needs a slice of AioCb,
122124
// and they must all be the same type. We're basically stuck with using an
123125
// unsafe function, since aio (as designed in C) is an unsafe API.
124-
pub unsafe fn from_slice(fd: RawFd, offs: off_t, buf: &[u8],
126+
pub unsafe fn from_slice(fd: RawFd, offs: off_t, buf: &'a [u8],
125127
prio: ::c_int, sigev_notify: SigevNotify,
126128
opcode: LioOpcode) -> AioCb {
127129
let mut a = AioCb::common_init(fd, prio, sigev_notify);
@@ -130,7 +132,7 @@ impl AioCb {
130132
a.aio_buf = buf.as_ptr() as *mut c_void;
131133
a.aio_lio_opcode = opcode as ::c_int;
132134

133-
let aiocb = AioCb { aiocb: a};
135+
let aiocb = AioCb { aiocb: a, phantom: PhantomData};
134136
aiocb
135137
}
136138

@@ -189,7 +191,7 @@ pub fn aio_fsync(mode: AioFsyncMode, aiocb: &mut AioCb) -> Result<()> {
189191
Errno::result(unsafe { libc::aio_fsync(mode as ::c_int, p) }).map(drop)
190192
}
191193

192-
/// Asynchously reads from a file descriptor into a buffer
194+
/// Asynchronously reads from a file descriptor into a buffer
193195
pub fn aio_read(aiocb: &mut AioCb) -> Result<()> {
194196
let p: *mut libc::aiocb = &mut aiocb.aiocb;
195197
Errno::result(unsafe { libc::aio_read(p) }).map(drop)

test/sys/test_aio.rs

Lines changed: 78 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn test_aio_suspend() {
121121
}
122122

123123
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
124-
assert!(aio_return(&mut rcb).unwrap() as usize == rbuf.len());
124+
assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len());
125125
}
126126

127127
// Test a simple aio operation with no completion notification. We must poll
@@ -133,17 +133,19 @@ fn test_aio_read() {
133133
const EXPECT: &'static [u8] = b"cdef";
134134
let mut f = tempfile().unwrap();
135135
f.write(INITIAL).unwrap();
136-
let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
137-
2, //offset
138-
&mut rbuf,
139-
0, //priority
140-
SigevNotify::SigevNone,
141-
LioOpcode::LIO_NOP);
142-
aio_read(&mut aiocb).unwrap();
143-
144-
let err = poll_aio(&mut aiocb);
145-
assert!(err == Ok(()));
146-
assert!(aio_return(&mut aiocb).unwrap() as usize == rbuf.len());
136+
{
137+
let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
138+
2, //offset
139+
&mut rbuf,
140+
0, //priority
141+
SigevNotify::SigevNone,
142+
LioOpcode::LIO_NOP);
143+
aio_read(&mut aiocb).unwrap();
144+
145+
let err = poll_aio(&mut aiocb);
146+
assert!(err == Ok(()));
147+
assert!(aio_return(&mut aiocb).unwrap() as usize == EXPECT.len());
148+
}
147149

148150
assert!(rbuf == EXPECT);
149151
}
@@ -241,29 +243,28 @@ fn test_lio_listio_wait() {
241243

242244
f.write(INITIAL).unwrap();
243245

244-
let mut wcb = unsafe {
245-
AioCb::from_slice( f.as_raw_fd(),
246-
2, //offset
247-
&WBUF,
248-
0, //priority
249-
SigevNotify::SigevNone,
250-
LioOpcode::LIO_WRITE)
251-
};
252-
253-
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
254-
8, //offset
255-
&mut rbuf,
256-
0, //priority
257-
SigevNotify::SigevNone,
258-
LioOpcode::LIO_READ);
259246
{
260-
let cbbuf = [&mut wcb, &mut rcb];
261-
let err = lio_listio(LioMode::LIO_WAIT, &cbbuf[..], SigevNotify::SigevNone);
247+
let mut wcb = unsafe {
248+
AioCb::from_slice( f.as_raw_fd(),
249+
2, //offset
250+
&WBUF,
251+
0, //priority
252+
SigevNotify::SigevNone,
253+
LioOpcode::LIO_WRITE)
254+
};
255+
256+
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
257+
8, //offset
258+
&mut rbuf,
259+
0, //priority
260+
SigevNotify::SigevNone,
261+
LioOpcode::LIO_READ);
262+
let err = lio_listio(LioMode::LIO_WAIT, &[&mut wcb, &mut rcb], SigevNotify::SigevNone);
262263
err.expect("lio_listio failed");
263-
}
264264

265-
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
266-
assert!(aio_return(&mut rcb).unwrap() as usize == rbuf.len());
265+
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
266+
assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len());
267+
}
267268
assert!(rbuf == b"3456");
268269

269270
f.seek(SeekFrom::Start(0)).unwrap();
@@ -286,31 +287,30 @@ fn test_lio_listio_nowait() {
286287

287288
f.write(INITIAL).unwrap();
288289

289-
let mut wcb = unsafe {
290-
AioCb::from_slice( f.as_raw_fd(),
291-
2, //offset
292-
&WBUF,
293-
0, //priority
294-
SigevNotify::SigevNone,
295-
LioOpcode::LIO_WRITE)
296-
};
297-
298-
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
299-
8, //offset
300-
&mut rbuf,
301-
0, //priority
302-
SigevNotify::SigevNone,
303-
LioOpcode::LIO_READ);
304290
{
305-
let cbbuf = [&mut wcb, &mut rcb];
306-
let err = lio_listio(LioMode::LIO_NOWAIT, &cbbuf[..], SigevNotify::SigevNone);
291+
let mut wcb = unsafe {
292+
AioCb::from_slice( f.as_raw_fd(),
293+
2, //offset
294+
&WBUF,
295+
0, //priority
296+
SigevNotify::SigevNone,
297+
LioOpcode::LIO_WRITE)
298+
};
299+
300+
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
301+
8, //offset
302+
&mut rbuf,
303+
0, //priority
304+
SigevNotify::SigevNone,
305+
LioOpcode::LIO_READ);
306+
let err = lio_listio(LioMode::LIO_NOWAIT, &[&mut wcb, &mut rcb], SigevNotify::SigevNone);
307307
err.expect("lio_listio failed");
308-
}
309308

310-
poll_aio(&mut wcb).unwrap();
311-
poll_aio(&mut rcb).unwrap();
312-
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
313-
assert!(aio_return(&mut rcb).unwrap() as usize == rbuf.len());
309+
poll_aio(&mut wcb).unwrap();
310+
poll_aio(&mut rcb).unwrap();
311+
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
312+
assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len());
313+
}
314314
assert!(rbuf == b"3456");
315315

316316
f.seek(SeekFrom::Start(0)).unwrap();
@@ -338,34 +338,33 @@ fn test_lio_listio_signal() {
338338

339339
f.write(INITIAL).unwrap();
340340

341-
let mut wcb = unsafe {
342-
AioCb::from_slice( f.as_raw_fd(),
343-
2, //offset
344-
&WBUF,
345-
0, //priority
346-
SigevNotify::SigevNone,
347-
LioOpcode::LIO_WRITE)
348-
};
349-
350-
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
351-
8, //offset
352-
&mut rbuf,
353-
0, //priority
354-
SigevNotify::SigevNone,
355-
LioOpcode::LIO_READ);
356-
unsafe {signaled = 0 };
357-
unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
358341
{
359-
let cbbuf = [&mut wcb, &mut rcb];
360-
let err = lio_listio(LioMode::LIO_NOWAIT, &cbbuf[..], sigev_notify);
342+
let mut wcb = unsafe {
343+
AioCb::from_slice( f.as_raw_fd(),
344+
2, //offset
345+
&WBUF,
346+
0, //priority
347+
SigevNotify::SigevNone,
348+
LioOpcode::LIO_WRITE)
349+
};
350+
351+
let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
352+
8, //offset
353+
&mut rbuf,
354+
0, //priority
355+
SigevNotify::SigevNone,
356+
LioOpcode::LIO_READ);
357+
unsafe {signaled = 0 };
358+
unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
359+
let err = lio_listio(LioMode::LIO_NOWAIT, &[&mut wcb, &mut rcb], sigev_notify);
361360
err.expect("lio_listio failed");
362-
}
363-
while unsafe { signaled == 0 } {
364-
thread::sleep(time::Duration::from_millis(10));
365-
}
361+
while unsafe { signaled == 0 } {
362+
thread::sleep(time::Duration::from_millis(10));
363+
}
366364

367-
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
368-
assert!(aio_return(&mut rcb).unwrap() as usize == rbuf.len());
365+
assert!(aio_return(&mut wcb).unwrap() as usize == WBUF.len());
366+
assert!(aio_return(&mut rcb).unwrap() as usize == WBUF.len());
367+
}
369368
assert!(rbuf == b"3456");
370369

371370
f.seek(SeekFrom::Start(0)).unwrap();

0 commit comments

Comments
 (0)