commit: 1abb194863318380186c2d568182709a928c7ea9
Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Sun Nov 23 15:23:59 2025 +0000
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Sun Nov 23 15:23:59 2025 +0000
URL: https://gitweb.gentoo.org/proj/steve.git/commit/?id=1abb1948
Do not open pidfd twice for the same process
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
steve.cxx | 56 ++++++++++++++++++++++++++++++++------------------------
1 file changed, 32 insertions(+), 24 deletions(-)
diff --git a/steve.cxx b/steve.cxx
index aeff215..6b359e8 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -54,12 +54,12 @@ struct steve_poll_waiter {
};
struct steve_process {
- int pid_fd;
+ int pid_fd{-1};
unsigned int tokens_held{0};
std::unique_ptr<struct event, std::function<void(struct event*)>> event;
~steve_process() {
- if (pid_fd != 0)
+ if (pid_fd != -1)
close(pid_fd);
}
};
@@ -139,32 +139,40 @@ static void steve_open(fuse_req_t req, struct
fuse_file_info *fi)
steve_state *state = static_cast<steve_state *>(fuse_req_userdata(req));
/* pid is not available in release, so store it here */
+ static_assert(sizeof(fi->fh) >= sizeof(context->pid));
fi->fh = context->pid;
- int pid_fd = syscall(SYS_pidfd_open, context->pid, 0);
- if (pid_fd == -1) {
- perror("unable to open pidfd, rejecting to open");
- fuse_reply_err(req, EIO);
- return;
- }
+ int pid_fd;
+ if (state->processes.find(fi->fh) != state->processes.end()) {
+ assert(state->processes[fi->fh].pid_fd != -1);
+ assert(state->processes[fi->fh].event);
+ pid_fd = state->processes[fi->fh].pid_fd;
+ } else {
+ pid_fd = syscall(SYS_pidfd_open, context->pid, 0);
+ if (pid_fd == -1) {
+ perror("unable to open pidfd, rejecting to open");
+ fuse_reply_err(req, EIO);
+ return;
+ }
- std::unique_ptr<struct event, std::function<void(struct event*)>>
- pidfd_event{event_new(state->evb, pid_fd, EV_READ|EV_PERSIST,
steve_handle_pidfd, state), event_free};
- if (!pidfd_event) {
- fprintf(stderr, "unable to allocate event for pidfd");
- close(pid_fd);
- fuse_reply_err(req, EIO);
- return;
- }
- if (event_add(pidfd_event.get(), nullptr) == -1) {
- fprintf(stderr, "failed to enable pidfd handler");
- close(pid_fd);
- fuse_reply_err(req, EIO);
- return;
- }
+ std::unique_ptr<struct event, std::function<void(struct
event*)>>
+ pidfd_event{event_new(state->evb, pid_fd,
EV_READ|EV_PERSIST, steve_handle_pidfd, state), event_free};
+ if (!pidfd_event) {
+ fprintf(stderr, "unable to allocate event for pidfd");
+ close(pid_fd);
+ fuse_reply_err(req, EIO);
+ return;
+ }
+ if (event_add(pidfd_event.get(), nullptr) == -1) {
+ fprintf(stderr, "failed to enable pidfd handler");
+ close(pid_fd);
+ fuse_reply_err(req, EIO);
+ return;
+ }
- state->processes[fi->fh].pid_fd = pid_fd;
- state->processes[fi->fh].event = std::move(pidfd_event);
+ state->processes[fi->fh].pid_fd = pid_fd;
+ state->processes[fi->fh].event = std::move(pidfd_event);
+ }
if (state->verbose)
printf("Device open by PID %ld (pidfd %d)\n", fi->fh, pid_fd);