Skip to content

Commit 386c50c

Browse files
committed
Merge #660
660: Fix double close bugs in test_lseek and test_lseek64 r=asomers std::fs::File closes the underlying file descriptor on Drop, without checking for errors. test_lseek and test_lseek64 also manually close the file descriptor. That works for single threaded test runs. But for multithreaded runs, it causes EBADF errors in other tests. Fix the tests by consuming the File with into_raw_fd(), so its drop method will never be called.
2 parents 1b1f15c + a50b476 commit 386c50c

File tree

3 files changed

+33
-29
lines changed

3 files changed

+33
-29
lines changed

test/test.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ mod test_stat;
2424
mod test_unistd;
2525

2626
use nixtest::assert_size_of;
27+
use std::os::unix::io::RawFd;
28+
use nix::unistd::read;
29+
30+
/// Helper function analogous to std::io::Read::read_exact, but for `RawFD`s
31+
fn read_exact(f: RawFd, buf: &mut [u8]) {
32+
let mut len = 0;
33+
while len < buf.len() {
34+
// get_mut would be better than split_at_mut, but it requires nightly
35+
let (_, remaining) = buf.split_at_mut(len);
36+
len += read(f, remaining).unwrap();
37+
}
38+
}
2739

2840
#[test]
2941
pub fn test_size_of_long() {

test/test_pty.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,7 @@ use nix::fcntl::{O_RDWR, open};
55
use nix::pty::*;
66
use nix::sys::stat;
77
use nix::sys::termios::*;
8-
use nix::unistd::{read, write, close};
9-
10-
/// Helper function analogous to std::io::Read::read_exact, but for `RawFD`s
11-
fn read_exact(f: RawFd, buf: &mut [u8]) {
12-
let mut len = 0;
13-
while len < buf.len() {
14-
// get_mut would be better than split_at_mut, but it requires nightly
15-
let (_, remaining) = buf.split_at_mut(len);
16-
len += read(f, remaining).unwrap();
17-
}
18-
}
8+
use nix::unistd::{write, close};
199

2010
/// Test equivalence of `ptsname` and `ptsname_r`
2111
#[test]
@@ -115,21 +105,21 @@ fn test_openpty() {
115105
let string = "foofoofoo\n";
116106
let mut buf = [0u8; 10];
117107
write(pty.master, string.as_bytes()).unwrap();
118-
read_exact(pty.slave, &mut buf);
108+
::read_exact(pty.slave, &mut buf);
119109

120110
assert_eq!(&buf, string.as_bytes());
121111

122112
// Read the echo as well
123113
let echoed_string = "foofoofoo\r\n";
124114
let mut buf = [0u8; 11];
125-
read_exact(pty.master, &mut buf);
115+
::read_exact(pty.master, &mut buf);
126116
assert_eq!(&buf, echoed_string.as_bytes());
127117

128118
let string2 = "barbarbarbar\n";
129119
let echoed_string2 = "barbarbarbar\r\n";
130120
let mut buf = [0u8; 14];
131121
write(pty.slave, string2.as_bytes()).unwrap();
132-
read_exact(pty.master, &mut buf);
122+
::read_exact(pty.master, &mut buf);
133123

134124
assert_eq!(&buf, echoed_string2.as_bytes());
135125

@@ -160,20 +150,20 @@ fn test_openpty_with_termios() {
160150
let string = "foofoofoo\n";
161151
let mut buf = [0u8; 10];
162152
write(pty.master, string.as_bytes()).unwrap();
163-
read_exact(pty.slave, &mut buf);
153+
::read_exact(pty.slave, &mut buf);
164154

165155
assert_eq!(&buf, string.as_bytes());
166156

167157
// read the echo as well
168158
let echoed_string = "foofoofoo\n";
169-
read_exact(pty.master, &mut buf);
159+
::read_exact(pty.master, &mut buf);
170160
assert_eq!(&buf, echoed_string.as_bytes());
171161

172162
let string2 = "barbarbarbar\n";
173163
let echoed_string2 = "barbarbarbar\n";
174164
let mut buf = [0u8; 13];
175165
write(pty.slave, string2.as_bytes()).unwrap();
176-
read_exact(pty.master, &mut buf);
166+
::read_exact(pty.master, &mut buf);
177167

178168
assert_eq!(&buf, echoed_string2.as_bytes());
179169

test/test_unistd.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use nix::sys::stat;
77
use std::iter;
88
use std::ffi::CString;
99
use std::fs::File;
10-
use std::io::{Write, Read};
10+
use std::io::Write;
1111
use std::os::unix::prelude::*;
1212
use std::env::current_dir;
1313
use tempfile::tempfile;
@@ -185,16 +185,17 @@ fn test_getcwd() {
185185
fn test_lseek() {
186186
const CONTENTS: &'static [u8] = b"abcdef123456";
187187
let mut tmp = tempfile().unwrap();
188-
tmp.write(CONTENTS).unwrap();
188+
tmp.write_all(CONTENTS).unwrap();
189+
let tmpfd = tmp.into_raw_fd();
189190

190191
let offset: off_t = 5;
191-
lseek(tmp.as_raw_fd(), offset, Whence::SeekSet).unwrap();
192+
lseek(tmpfd, offset, Whence::SeekSet).unwrap();
192193

193-
let mut buf = String::new();
194-
tmp.read_to_string(&mut buf).unwrap();
195-
assert_eq!(b"f123456", buf.as_bytes());
194+
let mut buf = [0u8; 7];
195+
::read_exact(tmpfd, &mut buf);
196+
assert_eq!(b"f123456", &buf);
196197

197-
close(tmp.as_raw_fd()).unwrap();
198+
close(tmpfd).unwrap();
198199
}
199200

200201
#[cfg(any(target_os = "linux", target_os = "android"))]
@@ -203,14 +204,15 @@ fn test_lseek64() {
203204
const CONTENTS: &'static [u8] = b"abcdef123456";
204205
let mut tmp = tempfile().unwrap();
205206
tmp.write(CONTENTS).unwrap();
207+
let tmpfd = tmp.into_raw_fd();
206208

207-
lseek64(tmp.as_raw_fd(), 5, Whence::SeekSet).unwrap();
209+
lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
208210

209-
let mut buf = String::new();
210-
tmp.read_to_string(&mut buf).unwrap();
211-
assert_eq!(b"f123456", buf.as_bytes());
211+
let mut buf = [0u8; 7];
212+
::read_exact(tmpfd, &mut buf);
213+
assert_eq!(b"f123456", &buf);
212214

213-
close(tmp.as_raw_fd()).unwrap();
215+
close(tmpfd).unwrap();
214216
}
215217

216218
execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh");

0 commit comments

Comments
 (0)