procfs icon indicating copy to clipboard operation
procfs copied to clipboard

No way to ignore `ESRCH` from `Process::stat`

Open bsilver8192 opened this issue 1 year ago • 1 comments

I don't think enough information is currently exposed to tell whether a Err from Process::stat represents ESRCH or not. I end up with an object like this:

Io(Custom { kind: Uncategorized, error: IoErrorWrapper { path: "/proc/2203430/stat", inner: Some(Os { code: 3, kind: Uncategorized, message: "No such process" }) } }, Some("/proc/2203430/stat"))

which hides the code: 3 part behind IoErrorWrapper, which isn't exposed in the API.

I don't want to ignore other errors that indicate bugs, but I do want to ignore processes disappearing.

I see 3 ways to fix it, I'd be happy to implement whichever one people think is best:

  • Have From<std::io::Error> for ProcError extract the inner and pass that to io::Error::new directly, so that as_ref.downcast.as_ref can extract the inner value with public APIs. (I think that's the right chain of methods? Need to do a lot of Option::map and turbofish, but I'm pretty sure it's possible.)
  • Map std::io::Error::raw_os_error() == Some(ESRCH) to ProcError::NotFound in From<std::io::Error> for ProcError. Probably want the same for EPERM, although that hasn't mattered yet for me.
  • Have From<std::io::Error> for ProcError use inner directly (instead of io) if it's an io::Error already.
  • Expose IoErrorWrapper or some kind of extract_inner(wrapper: &dyn Error) -> Option<&dyn Error> that downcasts to it.

Here's a reliable way to get one of these errors it in a test:

let mut command = Command::new("sleep").arg("10000").spawn().expect("Failed to start sleep");
let p = procfs::process::Process::new(command.id() as i32).expect("Failed to create Process");
command.kill().expect("Failed to kill sleep");
command.wait().expect("Failed to wait for sleep");
let e = p.stat().unwrap_err();

bsilver8192 avatar Sep 29 '22 18:09 bsilver8192

Hi, thanks for opening this issue. I agree this is an important gap in the procfs API. Of your 3 proposed suggestions, I'm currently learning towards the 2nd suggestion, which is to map the ESRCH into a ProcError::NotFound.

I also didn't realize how IoErrorWrapper hides its inner Error. I'd like to fix that too, probably by making its members public (I can't currently think of a reason to keep this type private).

I'd gratefully accept a PR for these two things, if you'd like to work on this.

eminence avatar Oct 03 '22 02:10 eminence