Skip to content

Commit d07a143

Browse files
Fix errno checking (#121)
* Correct the error checking of errno in listpids() and add a test for list pids by parent that doesn't exist * Only check errno when return value is zero as per C source here https://opensource.apple.com/source/Libc/Libc-498/darwin/libproc.c.auto.html
1 parent 41d9a0e commit d07a143

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

src/libproc/sys/macos.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ impl From<ProcFilter> for u32 {
3434

3535
// similar to list_pids_ret() below, there are two cases when 0 is returned, one when there are
3636
// no pids, and the other when there is an error
37+
// when `errno` is set to indicate an error in the input type, the return value is 0
3738
fn check_listpid_ret(ret: c_int) -> io::Result<Vec<u32>> {
38-
let errno = std::io::Error::last_os_error().raw_os_error().unwrap_or(0);
39-
if ret < 0 || (ret == 0 && errno < 0) {
39+
if ret < 0 || (ret == 0 && io::Error::last_os_error().raw_os_error().unwrap_or(0) != 0) {
4040
return Err(io::Error::last_os_error());
4141
}
4242

@@ -47,10 +47,13 @@ fn check_listpid_ret(ret: c_int) -> io::Result<Vec<u32>> {
4747
// Common code for handling the special case of listpids return, where 0 is a valid return
4848
// but is also used in the error case - so we need to look at errno to distringish between a valid
4949
// 0 return and an error return
50+
// when `errno` is set to indicate an error in the input type, the return value is 0
5051
fn list_pids_ret(ret: c_int, mut pids: Vec<u32>) -> io::Result<Vec<u32>> {
51-
let errno = std::io::Error::last_os_error().raw_os_error().unwrap_or(0);
5252
match ret {
53-
value if value < 0 || errno < 0 => Err(io::Error::last_os_error()),
53+
value if value < 0 ||
54+
(ret == 0 && io::Error::last_os_error().raw_os_error().unwrap_or(0) != 0) => {
55+
Err(io::Error::last_os_error())
56+
},
5457
_ => {
5558
let items_count = ret as usize / mem::size_of::<u32>();
5659
unsafe {
@@ -270,7 +273,7 @@ mod test {
270273
fn test_listpids_real_uid() {
271274
let mut bsdinfo_ruids: HashMap<_, HashSet<_>> = HashMap::new();
272275
for info in get_all_pid_bsdinfo()
273-
.expect("Could not get all pids info"){
276+
.expect("Could not get all pids info") {
274277
bsdinfo_ruids
275278
.entry(info.pbi_ruid)
276279
.and_modify(|pids| {
@@ -330,6 +333,13 @@ mod test {
330333
assert!(not_matched <= PROCESS_DIFF_TOLERANCE);
331334
}
332335

336+
#[test]
337+
fn test_listpids_invalid_parent_pid() {
338+
let pids = listpids(ProcFilter::ByParentProcess { ppid: u32::MAX })
339+
.expect("Error requesting children of inexistant process");
340+
assert!(pids.is_empty());
341+
}
342+
333343
// No point in writing test cases for all ProcFilter members, as the Darwin
334344
// implementation of proc_listpidspath is essentially a wrapper acound
335345
// proc_listpids with calls to proc_pidinfo to gather path information.
@@ -339,8 +349,9 @@ mod test {
339349
#[test]
340350
fn test_listpidspath() -> Result<(), io::Error> {
341351
let root = std::path::Path::new("/");
342-
let pids =
343-
listpidspath(ProcFilter::All, root, true, false).expect("Failed to load PIDs for path");
352+
let pids: Vec<u32> =
353+
listpidspath(ProcFilter::All, root, true, false)
354+
.expect("Failed to load PIDs for path");
344355
assert!(!pids.is_empty());
345356
Ok(())
346357
}

0 commit comments

Comments
 (0)