-
Notifications
You must be signed in to change notification settings - Fork 117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Process struct should carry an fd and use openat #125
Comments
Hi, Thanks for opening this issue. At first glance, this sounds like a nice improvement. Your example with "statm" and "status" is well motivated. I would be definitely willing to see a pull request in this area. One reason that the current API for all_processes() returns a You have a good point about needed to manage the large number of open FDs. How does returning an iterator help? If the caller immediately collects everything into a Vec, we would still have an open FD for every running process, right? |
Also, I don't see any support for |
That will ensure you get a list of pids that was active at the time of iteration but will not prevent the pids from becoming stale. The method I'm suggesting will be slower; that's unavoidable because it's moving from just holding the pid number to now having to do a syscall to grab a reference to a kernel resource. But it will also technically be more correct, the iterator can skip over pids that became stale during processing of the directory. If we want to preserve the quick iteration, I think it would make more sense to have the method return a
Yes. The idea is that for implementing something like
|
The result from all_processes is always wrong whichever method you use. It's better to minimize the number of opened file descriptors. Btw, it makes no sense to use a program like top on a system where pid sare reused faster than reading the result of all_processes(). |
It won't necessarily be wrong if a small number of fds are kept open, for example a top program might want to keep the fd to the currently highlighted process open. That process could then be signaled in a race-free way using pidfd. If the pids are re-used faster than top can read them (i.e. the openat to |
Under Linux, procfs can suffer from TOCTTOU caused by pid reuse. This is evident if you take the
self_memory
example and have it run on external process. I'll show some output from strace to illustrate the problem:In between calls to
openat
, our process could be pre-empted, and then the pid could potentially be killed and re-used by another process before our process resumes. This would result in the call toProcess::status()
returning wrong information, when really it should return an error because the original process 1234 it was referencing is dead. To fix the problem, you'd want the syscalls to look more like this:The easiest way to do this would be to replace every area where file paths are joined with an intentional call to openat. The net effect of this would be that
Process
would no longer storeroot
, it would store a handle to the directory in procfs. This should also be done when reading from entries in/proc/[pid]/task/[tid]
. Another change that should probably happen along with this is thatprocess::all_processes()
should return an Iterator instead of aVec
, that way it will prevent a huge number of file descriptors being opened at once. This is an API break so I'm proposing it here before submitting any pull request.The text was updated successfully, but these errors were encountered: