]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: make pidfd for the target process available while collecting fds
authorMasatake YAMATO <yamato@redhat.com>
Sun, 1 Feb 2026 16:28:17 +0000 (01:28 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Mon, 2 Feb 2026 18:22:45 +0000 (03:22 +0900)
This is a preparation change for adding inspect_target_fd method to
file_class.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
lsfd-cmd/lsfd.c
lsfd-cmd/lsfd.h

index 39523fa248a0209926a0b62a8ffa86d7eb6d39d7..c5735705758eebc65d37634361ae7b2e6ecb60fd 100644 (file)
@@ -843,6 +843,9 @@ static struct proc *new_proc(pid_t pid, struct proc *leader)
        INIT_LIST_HEAD(&proc->eventpolls);
 
        proc->kthread = 0;
+
+       proc->pidfd = -1;
+
        return proc;
 }
 
@@ -1106,24 +1109,27 @@ static void collect_execve_file(struct path_cxt *pc, struct proc *proc,
                               sockets_only);
 }
 
-static void collect_pidfs_file(struct proc *proc, bool sockets_only)
+static int collect_pidfs_file(struct proc *proc, bool sockets_only)
 {
        struct file *f = NULL;
        int pidfd;
 
        if (sockets_only)
-               return;
+               return -1;
 
        pidfd = pidfd_open(proc->pid, 0);
        if (pidfd < 0)
-               return;
+               return -1;
 
        {
                struct stat sb;
                const int assoc = ASSOC_PIDFS * -1;
 
-               if (fstat(pidfd, &sb) < 0)
-                       goto out;
+               if (fstat(pidfd, &sb) < 0) {
+                       /* Even fstat fails here, the pidfd is still
+                        * usable in the caller side. */
+                       return pidfd;
+               }
 
                if ((sb.st_mode & S_IFMT) == S_IFREG) {
                        char *name = NULL;
@@ -1151,8 +1157,7 @@ static void collect_pidfs_file(struct proc *proc, bool sockets_only)
                free(fdinfo);
        }
 
- out:
-       close(pidfd);
+       return pidfd;
 }
 
 static void collect_fs_files(struct path_cxt *pc, struct proc *proc,
@@ -2079,6 +2084,7 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
        }
        if (proc->kthread && !ctl->threads) {
                free_proc(proc);
+               proc = NULL;
                goto out;
        }
 
@@ -2088,7 +2094,7 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
            || kcmp(proc->leader->pid, proc->pid, KCMP_FS, 0, 0) != 0)
                collect_fs_files(pc, proc, ctl->sockets_only);
 
-       collect_pidfs_file(proc, ctl->sockets_only);
+       proc->pidfd = collect_pidfs_file(proc, ctl->sockets_only);
 
        /* Reading /proc/$pid/mountinfo is expensive.
         * mnt_namespaces is a table for avoiding reading mountinfo files
@@ -2165,6 +2171,11 @@ static void read_process(struct lsfd_control *ctl, struct path_cxt *pc,
                walk_threads(ctl, pc, pid, proc, parse_proc_syscall);
 
  out:
+       if (proc && proc->pidfd >= 0) {
+               close(proc->pidfd);
+               proc->pidfd = -1;
+       }
+
        /* Let's be careful with number of open files */
        ul_path_close_dirfd(pc);
 }
index 469e58bce115e4b3ea7ecadf6231956891fab538..626027a4a7adb24ab4ae9dcaee9c24b6211df163 100644 (file)
@@ -189,6 +189,7 @@ struct proc {
        struct list_head files;
        unsigned int kthread: 1;
        struct list_head eventpolls;
+       int pidfd;
 };
 
 struct proc *get_proc(pid_t pid);