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);

Reply via email to